Dan*_*bbs 9 sql arrays postgresql intersection aggregate-functions
我有一个视图定义为:
CREATE VIEW View1 AS
SELECT Field1, Field2, array_agg(Field3) AS AggField
FROM Table1
GROUP BY Field1, Field2;
Run Code Online (Sandbox Code Playgroud)
我想要做的是获得数组的交集,AggField
例如:
SELECT intersection(AggField) FROM View1 WHERE Field2 = 'SomeValue';
Run Code Online (Sandbox Code Playgroud)
这是可能的,还是有更好的方法来实现我想要的?
mu *_*ort 18
我能想到的最接近阵列交叉点的是:
select array_agg(e)
from (
select unnest(a1)
intersect
select unnest(a2)
) as dt(e)
Run Code Online (Sandbox Code Playgroud)
这假定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;
Run Code Online (Sandbox Code Playgroud)
然后你可以做这样的事情:
=> 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)
Run Code Online (Sandbox Code Playgroud)
请注意,这并不保证返回数组中的任何特定顺序,但如果您关心它,则可以修复它.然后你可以创建自己的聚合函数:
-- 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[]
);
Run Code Online (Sandbox Code Playgroud)
而现在我们看到为什么array_intersect
有趣的和有点kludgey事情与NULLs.我们需要一个聚合的初始值,其行为类似于通用集合,我们可以使用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)
Run Code Online (Sandbox Code Playgroud)
不是简单或有效,但可能是一个合理的起点,总比没有好.
有用的参考:
归档时间: |
|
查看次数: |
6035 次 |
最近记录: |