微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

PostgreSQL中多个数组的交集

我有一个定义为:
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

原文地址:https://www.jb51.cc/postgresql/191733.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐