PostgreSQLには同じ長さの2つの配列値があります。
{a,b,c}
と{d,e,f}
それらを組み合わせて
{{a,d},{b,e},{c,f}}
それを行う方法はありますか?
PostgreSQLには同じ長さの2つの配列値があります。
{a,b,c}
と{d,e,f}
それらを組み合わせて
{{a,d},{b,e},{c,f}}
それを行う方法はありますか?
持っているarray_agg(array expression)
:
array_agg
(anyarray
)→anyarray
すべての入力配列を1つの高次元の配列に連結します。(入力はすべて同じ次元である必要があり、空またはnullにすることはできません。)
array_agg_mult()
これは、以下に示すカスタム集計関数のドロップイン置換です。これはCで実装されており、かなり高速です。これを使って。
複数の配列を並行してアンネストするROWS FROM
構造または更新を使用します。unnest()
それぞれの長さを変えることができます。あなたは(ドキュメントごとに)得ます:
[...]この場合の結果行の数は、最大の関数結果の数であり、小さい結果には一致するnull値が埋め込まれます。
このよりクリーンでシンプルなバリアントを使用してください。
SELECT ARRAY[a,b] AS ab
FROM unnest('{a,b,c}'::text[]
, '{d,e,f}'::text[]) x(a,b);
Postgres9.3以前の次のデモを検討してください。
SELECT ARRAY[a,b] AS ab
FROM (
SELECT unnest('{a,b,c}'::text[]) AS a
, unnest('{d,e,f}'::text[]) AS b
) x;
結果:
ab
-------
{a,d}
{b,e}
{c,f}
並列にネストを解除するには、両方の配列に同じ数の要素が必要であることに注意してください。そうしないと、代わりにクロス結合が発生します。
次の場合は、これを関数にラップできます。
CREATE OR REPLACE FUNCTION zip(anyarray, anyarray)
RETURNS SETOF anyarray LANGUAGE SQL AS
$func$
SELECT ARRAY[a,b] FROM (SELECT unnest($1) AS a, unnest($2) AS b) x;
$func$;
電話:
SELECT zip('{a,b,c}'::text[],'{d,e,f}'::text[]);
同じ結果。
ここで、その新しい配列のセットを1つの2次元配列に集約する場合は、さらに複雑になります。
SELECT ARRAY (SELECT ...)
また:
SELECT array_agg(ARRAY[a,b]) AS ab
FROM (
SELECT unnest('{a,b,c}'::text[]) AS a
,unnest('{d,e,f}'::text[]) AS b
) x
また:
SELECT array_agg(ARRAY[ARRAY[a,b]]) AS ab
FROM ...
すべて同じエラーメッセージが表示されます(9.1.5ページでテスト済み):
エラー:データ型text[]の配列型が見つかりませんでした
しかし、この密接に関連する質問の下で解決したので、これを回避する方法があります。
カスタム集計関数を作成します。
CREATE AGGREGATE array_agg_mult (anyarray) (
SFUNC = array_cat
, STYPE = anyarray
, INITCOND = '{}'
);
そして、次のように使用します。
SELECT array_agg_mult(ARRAY[ARRAY[a,b]]) AS ab
FROM (
SELECT unnest('{a,b,c}'::text[]) AS a
, unnest('{d,e,f}'::text[]) AS b
) x
結果:
{{a,d},{b,e},{c,f}}
追加のレイヤーに注意してくださいARRAY[]
!それなしでただ:
SELECT array_agg_mult(ARRAY[a,b]) AS ab
FROM ...
あなたが得る:
{a,d,b,e,c,f}
これは他の目的に役立つかもしれません。
別の関数をロールします:
CREATE OR REPLACE FUNCTION zip2(anyarray, anyarray)
RETURNS SETOF anyarray LANGUAGE SQL AS
$func$
SELECT array_agg_mult(ARRAY[ARRAY[a,b]])
FROM (SELECT unnest($1) AS a, unnest($2) AS b) x;
$func$;
電話:
SELECT zip2('{a,b,c}'::text[],'{d,e,f}'::text[]); -- or any other array type
結果:
{{a,d},{b,e},{c,f}}
Erwinが言及した配列マルチアグリゲーションを使用して、長さが異なる配列に対して安全な別のアプローチを次に示します。
CREATE OR REPLACE FUNCTION zip(array1 anyarray, array2 anyarray) RETURNS text[]
AS $$
SELECT array_agg_mult(ARRAY[ARRAY[array1[i],array2[i]]])
FROM generate_subscripts(
CASE WHEN array_length(array1,1) >= array_length(array2,1) THEN array1 ELSE array2 END,
1
) AS subscripts(i)
$$ LANGUAGE sql;
regress=> SELECT zip('{a,b,c}'::text[],'{d,e,f}'::text[]);
zip
---------------------
{{a,d},{b,e},{c,f}}
(1 row)
regress=> SELECT zip('{a,b,c}'::text[],'{d,e,f,g}'::text[]);
zip
------------------------------
{{a,d},{b,e},{c,f},{NULL,g}}
(1 row)
regress=> SELECT zip('{a,b,c,z}'::text[],'{d,e,f}'::text[]);
zip
------------------------------
{{a,d},{b,e},{c,f},{z,NULL}}
(1 row)
nullパディングではなく余分な部分を切り落としたい場合は、代わりに>=
長さテストをに変更してください。<=
この関数は、配列に1以外の記述要素がある可能性があるというかなり奇妙なPostgreSQL機能を処理しませんが、実際には誰もその機能を実際に使用しません。たとえば、インデックスがゼロの3要素配列の場合:
regress=> SELECT zip('{a,b,c}'::text[], array_fill('z'::text, ARRAY[3], ARRAY[0]));
zip
------------------------
{{a,z},{b,z},{c,NULL}}
(1 row)
wheras Erwinのコードは、そのような配列で機能し、多次元配列(それらをフラット化することによって)でも機能しますが、長さが異なる配列では機能しません。
配列はPostgreSQLでは少し特殊で、多次元配列、構成可能なオリジンインデックスなどでは少し柔軟性があります。
9.4では、次のように書くことができます。
SELECT array_agg_mult(ARRAY[ARRAY[a,b])
FROM unnest(array1) WITH ORDINALITY as (o,a)
NATURAL FULL OUTER JOIN
unnest(array2) WITH ORDINALITY as (o,b);
これは、特に、並べ替えと結合を行うのではなく、関数を一緒にスキャンするための最適化が行われる場合に、はるかに優れています。