Cách lý tưởng sẽ là bình thường hóa dữ liệu của bạn và chia hai thành phần của cột thành hai cột riêng lẻ. Một trong các loại integer
, một text
.
Với bảng hiện tại, bạn có thể làm điều gì đó như được minh họa ở đây:
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
Cùng một substring()
biểu thức có thể được sử dụng để tách cột.
Các biểu thức chính quy có phần chịu được lỗi:
-
Regex đầu tiên chọn chuỗi số dài nhất từ bên trái,
NULL
nếu không có chữ số nào được tìm thấy, do đó, truyền thànhinteger
không thể sai. -
Regex thứ hai chọn phần còn lại của chuỗi từ ký tự đầu tiên không phải là chữ số hoặc '_'.
Nếu dấu gạch dưới vẫn rõ ràng là dấu phân cách, hãy split_part()
nhanh hơn:
ORDER BY (split_part(t, '_', 1)::int
,split_part(t, '_', 2)
Câu trả lời cho ví dụ của bạn
SELECT name
FROM nametable
ORDER BY (split_part(name, '_', 1)::int
,split_part(name, '_', 2)