29

データベースには、次の形式のさまざまな英数字の文字列があります。

10_asdaasda
100_inkskabsjd
11_kancaascjas
45_aksndsialcn
22_dsdaskjca
100_skdnascbka

基本的に、文字列の前の数字と文字列名自体で並べ替えたいのですが、もちろん、文字は1つずつ比較されるため、名前による順序付けの結果は次のようになります。

10_asdaasda
100_inkskabsjd
100_skdnascbka
11_kancaascjas
22_dsdaskjca
45_aksndsialcn

私が好む順序の代わりに:

10_asdaasda
11_kancaascjas
22_dsdaskjca
45_aksndsialcn
100_inkskabsjd
100_skdnascbka

正直なところ、文字列を前の数字で並べ替えれば大丈夫です。私はPostgreSQLにあまり詳しくないので、これを行うための最良の方法が何であるかわかりませんでした。助けていただければ幸いです!

4

4 に答える 4

44

理想的な方法は、設計を正規化し、列の2つのコンポーネントを2つの別々の列に分割することです。タイプintegerの1つ、1つtext

現在のテーブルを使用すると、次のことができます。

SELECT col
FROM   tbl
ORDER  BY (substring(col, '^[0-9]+'))::int  -- cast to integer
         , substring(col, '[^0-9_].*$');    -- works as text

同じsubstring()を使用して列を分割できます。

これらの正規表現は、フォールトトレラントです。最初の正規表現は、数字が見つからない場合
、左から最も長い数値文字列を選択するため、キャストが間違ってしまうことはありません。 2番目の正規表現は、数字または「_」ではない最初の文字から文字列の残りの部分を選択します。NULLinteger

アンダースコア(_)が明確な区切り文字である場合は、次のようsplit_part()になります。

SELECT col
FROM   tbl
ORDER  BY split_part(col, '_', 1)::int
        , split_part(col, '_', 2);

ここでdb<>フィドル

見る:

于 2012-07-10T16:58:46.120 に答える
9

部分文字列で正規表現を使用できます

   order by substring(column, '^[0-9]+')::int, substring(column, '[^0-9]*$')
于 2013-06-21T18:33:40.943 に答える
4

式のインデックスを使用してこれを行う方法があります。それは私の好ましい解決策ではありませんが(私はBradのものを選びます)、次の式にインデックスを作成できます(それを行う方法は他にもあります)。

CREATE INDEX idx_name ON table (CAST(SPLIT_PART(columname, '_', 1) AS integer));  

CAST(SPLIT_PART(columname, '_', 1) AS integer)次に、下線文字の前の番号が必要になるたびに 、次のように検索して並べ替えることができます。

SELECT * FROM table ORDER BY CAST(SPLIT_PART(columname, '_', 1) AS integer);  

にインデックスを作成して文字列部分にも同じことを行い、SPLIT_PART(columname, '_', 2)それに応じて並べ替えることもできます。
しかし、私が言ったように、私はこの解決策が非常に醜いと思います。私は間違いなく他の2つの列(1つは数値用、もう1つは文字列用)を使用し、次にここで言及した列を削除することもできます。

于 2012-07-10T17:03:31.760 に答える
1

数値データ型の新しい列をデータベースに追加し、新しいレコードを永続化するときに、使用している文字列値のプレフィックスと同じ値に設定する必要があります。

次に、適切に入力された数値列にインデックスを作成して並べ替えることができます。

于 2012-07-10T16:53:26.513 に答える