我有一个定义为:
CREATE VIEW View1 AS SELECT Field1,Field2,array_agg(Field3) AS AggField FROM Table1 GROUP BY Field1,Field2;
我想做的是让AggField中的数组与以下类似:
SELECT intersection(AggField) FROM View1 WHERE Field2 = 'SomeValue';
这是否可能,还是有更好的方式来实现我想要的?
我可以想到的与阵列交点最近的事情是这样的:
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 -- 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,5,7,9,10]); array_intersect ----------------- {6,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,3} {1,3} {3,5} (3 rows) > select array_intersect_agg(a) from stuff; array_intersect_agg --------------------- {3} (1 row)
不完全简单或高效,但可能是一个合理的起点,而不是完全没有.
实用参考文献
> array_agg
> create aggregate
> create function
> PL/pgSQL
> unnest