我能想到的最接近数组交集的方法是这样的:
select array_agg(e)
from (
select unnest(a1)
intersect
select unnest(a2)
) as dt(e)
假设
a1
和
a2
是具有相同类型元素的单维数组。您可以将其封装在以下类似函数中:
create function array_intersect(a1 int[], a2 int[]) returns int[] as $$
declare
ret int[];
begin
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)
请注意,这并不保证返回数组中的任何特定顺序,但如果您关心顺序,您可以解决这个问题。然后,您可以创建自己的聚合函数:
create aggregate array_intersect_agg(
sfunc = array_intersect,
basetype = int[],
stype = int[],
initcond = NULL
);
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)
并不是非常简单或高效,但可能是一个合理的起点,总比什么都没有要好。
有用的参考资料:
&
)。 - user330315dt
的“表”是指 UNION,并且它的“列”名为e
。 - mu is too short