La forma ideal sería normalizar sus datos y divida los dos componentes de la columna en dos columnas individuales. Uno de tipo integer
, un text
.
Con la tabla actual, puede hacer algo como lo que se muestra aquí:
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
La misma substring()
se pueden usar expresiones para dividir la columna.
Las expresiones regulares son algo tolerantes a fallas:
-
La primera expresión regular elige la cadena numérica más larga de la izquierda,
NULL
si no se encuentran dígitos, entonces la conversión ainteger
no puede salir mal. -
La segunda expresión regular elige el resto de la cadena del primer carácter que no es un dígito o '_'.
Si el guión bajo no es ambiguo como separador de todos modos, split_part()
es más rápido:
ORDER BY (split_part(t, '_', 1)::int
,split_part(t, '_', 2)
Respuesta para tu ejemplo
SELECT name
FROM nametable
ORDER BY (split_part(name, '_', 1)::int
,split_part(name, '_', 2)