私が考えることができる配列交差点に最も近いものはこれです:
select array_agg(e)
from (
select unnest(a1)
intersect
select unnest(a2)
) as dt(e)
これは、a1
が およびa2
同じタイプの要素を持つ1次元配列です。これを次のような関数にまとめることができます:
create function array_intersect(a1 int[], a2 int[]) returns int[] as $$
declare
ret int[];
begin
-- The reason for the kludgy NULL handling comes later.
if a1 is null then
return a2;
elseif a2 is null then
return a1;
end if;
select array_agg(e) into ret
from (
select unnest(a1)
intersect
select unnest(a2)
) as dt(e);
return ret;
end;
$$ language plpgsql;
次に、次のようなことを行うことができます:
=> select array_intersect(ARRAY[2,4,6,8,10], ARRAY[1,2,3,4,5,6,7,8,9,10]);
array_intersect
-----------------
{6,2,4,10,8}
(1 row)
これは、返される配列の特定の順序を保証するものではありませんが、気になる場合は修正できることに注意してください。次に、独自の集計関数を作成できます:
-- Pre-9.1
create aggregate array_intersect_agg(
sfunc = array_intersect,
basetype = int[],
stype = int[],
initcond = NULL
);
-- 9.1+ (AFAIK, I don't have 9.1 handy at the moment
-- see the comments below.
create aggregate array_intersect_agg(int[]) (
sfunc = array_intersect,
stype = int[]
);
そして今、なぜarray_intersect
NULLを使用して、面白くてやや厄介なことを行います。ユニバーサルセットのように動作する集計の初期値が必要であり、そのためにNULLを使用できます(はい、これは少し臭いがしますが、頭のてっぺんからこれ以上良いものは考えられません)。
これがすべて整ったら、次のようなことができます:
> select * from stuff;
a
---------
{1,2,3}
{1,2,3}
{3,4,5}
(3 rows)
> select array_intersect_agg(a) from stuff;
array_intersect_agg
---------------------
{3}
(1 row)
正確に単純または効率的ではありませんが、おそらく合理的な出発点であり、何もないよりはましです。
役立つ参考資料:
-
array_agg
- 集計を作成
- 関数の作成
- PL / pgSQL
-
unnest