Идеалният начин би бил нормализирането вашите данни и разделете двата компонента на колоната на две отделни колони. Един от типа integer
, един text
.
С текущата таблица можете да направите нещо като демонстрирано тук:
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
Същият substring()
изразите могат да се използват за разделяне на колоната.
Регулярните изрази са донякъде устойчиви на грешки:
-
Първият регулярен израз избира най-дългия числов низ отляво,
NULL
ако не са намерени цифри, прехвърлянето къмinteger
не може да се обърка. -
Вторият регулярен израз избира останалата част от низа от първия знак, който не е цифра или „_“.
Ако долната черта все пак е недвусмислена като разделител, split_part()
е по-бързо:
ORDER BY (split_part(t, '_', 1)::int
,split_part(t, '_', 2)
Отговор за вашия пример
SELECT name
FROM nametable
ORDER BY (split_part(name, '_', 1)::int
,split_part(name, '_', 2)