Det ideala sättet skulle vara att normalisera dina data och dela upp de två komponenterna i kolumnen i två individuella kolumner. En av typen integer
, en text
.
Med den aktuella tabellen kan du göra något som visas här:
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
Samma substring()
uttryck kan användas för att dela kolumnen.
De reguljära uttrycken är något feltoleranta:
-
Det första regexet väljer den längsta numeriska strängen från vänster,
NULL
om inga siffror hittas, så cast tillinteger
kan inte gå fel. -
Det andra regexet väljer resten av strängen från det första tecknet som inte är en siffra eller '_'.
Om understrecket ändå är entydigt som separator, split_part()
är snabbare:
ORDER BY (split_part(t, '_', 1)::int
,split_part(t, '_', 2)
Svar för ditt exempel
SELECT name
FROM nametable
ORDER BY (split_part(name, '_', 1)::int
,split_part(name, '_', 2)