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

要素番号を持つPostgreSQLunnest()

    Postgres9.4以降

    WITH ORDINALITYを使用する セットを返す関数の場合:

    FROMの関数の場合 句の接尾辞はWITH ORDINALITYbigint 列は、関数の出力の各行に対して1から始まり、1ずつ増加する出力に追加されます。これは、unnest()などの集合戻り関数の場合に最も役立ちます。 。

    LATERALと組み合わせて pg 9.3以降の機能であり、pgsql-hackersのこのスレッドによると、上記のクエリは次のように記述できます。

    SELECT t.id, a.elem, a.nr
    FROM   tbl AS t
    LEFT   JOIN LATERAL unnest(string_to_array(t.elements, ','))
                        WITH ORDINALITY AS a(elem, nr) ON TRUE;

    LEFT JOIN ... ON TRUE 右側のテーブル式が行を返さない場合でも、左側のテーブルのすべての行を保持します。それが問題にならない場合は、これと同等の冗長性の少ないを使用できます。 暗黙のCROSS JOIN LATERALを含むフォーム :

    SELECT t.id, a.elem, a.nr
    FROM   tbl t, unnest(string_to_array(t.elements, ',')) WITH ORDINALITY a(elem, nr);
    

    または、実際の配列に基づいている場合はもっと簡単です (arr 配列列であること):

    SELECT t.id, a.elem, a.nr
    FROM   tbl t, unnest(t.arr) WITH ORDINALITY a(elem, nr);
    

    または、最小限の構文で:

    SELECT id, a, ordinality
    FROM   tbl, unnest(arr) WITH ORDINALITY a;
    

    a 自動的にテーブルおよび 列エイリアス。追加された通常の列のデフォルト名はordinalityです。 。ただし、明示的な列エイリアスとテーブル修飾列を追加することをお勧めします(より安全でクリーンです)。

    Postgres 8.4-9.3

    row_number() OVER (PARTITION BY id ORDER BY elem)を使用 元の序数の序数ではなく、並べ替え順序に従って番号を取得します 文字列内。

    ORDER BYは省略できます :

    SELECT *, row_number() OVER (PARTITION by id) AS nr
    FROM  (SELECT id, regexp_split_to_table(elements, ',') AS elem FROM tbl) t;
    

    これは正常に機能し、単純なクエリで失敗するのを見たことがありませんが、PostgreSQLはORDER BYのない行の順序に関して何も主張しません。 。実装の詳細により、たまたま機能します。

    序数を保証する 空白で区切られた文字列の要素の数 :

    SELECT id, arr[nr] AS elem, nr
    FROM  (
       SELECT *, generate_subscripts(arr, 1) AS nr
       FROM  (SELECT id, string_to_array(elements, ' ') AS arr FROM tbl) t
       ) sub;
    

    または、実際の配列に基づいている場合はもっと簡単です :

    SELECT id, arr[nr] AS elem, nr
    FROM  (SELECT *, generate_subscripts(arr, 1) AS nr FROM tbl) t;

    dba.SEに関する関連回答:

    • ネストされていない配列の要素の元の順序を保持するにはどうすればよいですか?

    Postgres 8.1-8.4

    これらの機能はまだ利用できません:RETURNS TABLEgenerate_subscripts()unnest()array_length() 。しかし、これは機能します:

    CREATE FUNCTION f_unnest_ord(anyarray, OUT val anyelement, OUT ordinality integer)
      RETURNS SETOF record
      LANGUAGE sql IMMUTABLE AS
    'SELECT $1[i], i - array_lower($1,1) + 1
     FROM   generate_series(array_lower($1,1), array_upper($1,1)) i';
    

    特に、配列インデックスは要素の順序位置とは異なる場合があることに注意してください。この拡張機能を備えたデモを検討してください :

    CREATE FUNCTION f_unnest_ord_idx(anyarray, OUT val anyelement, OUT ordinality int, OUT idx int)
      RETURNS SETOF record
      LANGUAGE sql IMMUTABLE AS
    'SELECT $1[i], i - array_lower($1,1) + 1, i
     FROM   generate_series(array_lower($1,1), array_upper($1,1)) i';
    
    SELECT id, arr, (rec).*
    FROM  (
       SELECT *, f_unnest_ord_idx(arr) AS rec
       FROM  (VALUES (1, '{a,b,c}'::text[])  --  short for: '[1:3]={a,b,c}'
                   , (2, '[5:7]={a,b,c}')
                   , (3, '[-9:-7]={a,b,c}')
          ) t(id, arr)
       ) sub;
    
     id |       arr       | val | ordinality | idx
    ----+-----------------+-----+------------+-----
      1 | {a,b,c}         | a   |          1 |   1
      1 | {a,b,c}         | b   |          2 |   2
      1 | {a,b,c}         | c   |          3 |   3
      2 | [5:7]={a,b,c}   | a   |          1 |   5
      2 | [5:7]={a,b,c}   | b   |          2 |   6
      2 | [5:7]={a,b,c}   | c   |          3 |   7
      3 | [-9:-7]={a,b,c} | a   |          1 |  -9
      3 | [-9:-7]={a,b,c} | b   |          2 |  -8
      3 | [-9:-7]={a,b,c} | c   |          3 |  -7
    

    比較:

    • 1次元配列の配列添え字を正規化して、1で始まるようにします


    1. PythonからのSQLServerストアドプロシージャの使用(pyodbc)

    2. MySQL –ランダム番号を生成する方法

    3. 特別なクエリの概要

    4. SQLSTATE [42000]:構文エラーまたはアクセス違反:1064 SQL構文にエラーがあります— PHP — PDO