sql >> データベース >  >> RDS >> PostgreSQL

単語と数字の混合文字列の人間化または自然数の並べ替え

    テストデータに基づいて構築しますが、これは任意のデータで機能します。これは、文字列内の任意の数の要素で機能します。

    1つのtextで構成される複合型を登録します および1つのinteger データベースごとに1回の値。私はそれをaiと呼んでいます :

    CREATE TYPE ai AS (a text, i int);

    秘訣は、aiの配列を形成することです 列の各値から。

    regexp_matches() パターン(\D*)(\d*) およびg オプションは、文字と数字の組み合わせごとに1行を返します。さらに、2つの空の文字列を含む1つの無関係なぶら下がり行'{"",""}' フィルタリングまたは抑制すると、コストが増えるだけです。空の文字列(''を置き換えた後、これを配列に集約します )with 0 integer コンポーネント(''として integerにキャストできません 。

    NULL 値は最初に並べ替えられます(または、特殊なケースで指定する必要があります)。または、STRICTでシバン全体を使用します @Craigが提案するような機能。

    Postgres9.4以降

    SELECT data
    FROM   alnum
    ORDER  BY ARRAY(SELECT ROW(x[1], CASE x[2] WHEN '' THEN '0' ELSE x[2] END)::ai
                    FROM regexp_matches(data, '(\D*)(\d*)', 'g') x)
            , data;
    

    db<>ここでフィドル

    Postgres 9.1(元の回答)

    PostgreSQL 9.1.5でテスト済み。ここで、regexp_replace() 動作が少し異なりました。

    SELECT data
    FROM  (
        SELECT ctid, data, regexp_matches(data, '(\D*)(\d*)', 'g') AS x
        FROM   alnum
        ) x
    GROUP  BY ctid, data   -- ctid as stand-in for a missing pk
    ORDER  BY regexp_replace (left(data, 1), '[0-9]', '0')
            , array_agg(ROW(x[1], CASE x[2] WHEN '' THEN '0' ELSE x[2] END)::ai)
            , data         -- for special case of trailing 0
    

    regexp_replace (left(data, 1), '[1-9]', '0')を追加します 最初のORDER BY 先頭の数字と空の文字列を処理するアイテム。

    {}()"',などの特殊文字の場合 発生する可能性がある場合は、それに応じてそれらをエスケープする必要があります。
    @CraigによるROWの使用の提案 表現がそれを処理します。

    BTW、これはsqlfiddleでは実行されませんが、私のdbクラスターでは実行されます。 JDBCはそれに対応していません。 sqlfiddleの文句:

    メソッドorg.postgresql.jdbc3.Jdbc3Array.getArrayImpl(long、int、Map)はまだ実装されていません。

    これはその後修正されました:http://sqlfiddle.com/#!17 / fad6e / 1



    1. MySQLで複数の行を1つの列に連結する方法

    2. ビューでストアドプロシージャを呼び出す方法は?

    3. 文字列を16進数に、またはその逆に変換するにはどうすればよいですか?

    4. PostgreSQL 11:新機能