理想的な方法は、正規化することです。 データを取得し、列の2つのコンポーネントを2つの個別の列に分割します。タイプinteger
の1つ 、1つの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
にキャストします 間違いはありません。 -
2番目の正規表現は、数字または「_」ではない最初の文字から文字列の残りの部分を選択します。
とにかくアンダースコアがセパレータとして明確である場合は、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)