Cara yang ideal adalah dengan menormalkan data Anda dan pisahkan dua komponen kolom menjadi dua kolom terpisah. Salah satu jenis integer
, satu text
.
Dengan tabel saat ini, Anda dapat melakukan sesuatu seperti yang ditunjukkan di sini:
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()
yang sama ekspresi dapat digunakan untuk memisahkan kolom.
Ekspresi reguler agak toleran terhadap kesalahan:
-
Regex pertama mengambil string numerik terpanjang dari kiri,
NULL
jika tidak ada digit yang ditemukan, jadi berikan keinteger
tidak bisa salah. -
Regex kedua mengambil sisa string dari karakter pertama yang bukan digit atau '_'.
Jika garis bawah tidak ambigu sebagai pemisah, split_part()
lebih cepat:
ORDER BY (split_part(t, '_', 1)::int
,split_part(t, '_', 2)
Jawab untuk contoh Anda
SELECT name
FROM nametable
ORDER BY (split_part(name, '_', 1)::int
,split_part(name, '_', 2)