L'idéal serait de normaliser vos données et divisez les deux composants de la colonne en deux colonnes individuelles. Un de type integer
, un text
.
Avec le tableau actuel, vous pouvez faire quelque chose comme démontré ici :
WITH x(t) AS (
VALUES
('10_asdaasda')
,('100_inkskabsjd')
,('11_kancaascjas')
,('45_aksndsialcn')
,('22_dsdaskjca')
,('100_skdnascbka')
)
SELECT t
FROM x
ORDER BY (substring(t, '^[0-9]+'))::int -- cast to integer
,substring(t, '[^0-9_].*$') -- works as text
Le même substring()
des expressions peuvent être utilisées pour diviser la colonne.
Les expressions régulières sont quelque peu tolérantes aux pannes :
-
La première regex sélectionne la chaîne numérique la plus longue à partir de la gauche,
NULL
si aucun chiffre n'est trouvé, donc le cast eninteger
ne peut pas se tromper. -
La deuxième regex sélectionne le reste de la chaîne à partir du premier caractère qui n'est pas un chiffre ou '_'.
Si le trait de soulignement est de toute façon sans ambiguïté comme séparateur, split_part()
est plus rapide :
ORDER BY (split_part(t, '_', 1)::int
,split_part(t, '_', 2)
Répondez à votre exemple
SELECT name
FROM nametable
ORDER BY (split_part(name, '_', 1)::int
,split_part(name, '_', 2)