从Postgres中的数组列聚合的不同值的数组

时间:2013-02-18 11:49:44

标签: sql arrays postgresql aggregate-functions

假设我们(在PostgreSQL 9.1中)有一个带有一些标识符的表,一个类型为integer []的列和一些其他列(至少有一个,尽管可能有更多)的整数类型(或任何其他可以求和的列) )。

目标是为“summable”列的每个标识符和数组列的所有不同元素的数组提供聚合。

我能找到的唯一方法是在子查询中的数组列上使用不需要的函数,而不是将其与聚合“可累计”列的另一个子查询连接。

一个简单的例子如下:

CREATE TEMP TABLE a (id integer, aint integer[], summable_val integer);
INSERT INTO a VALUES
(1, array[1,2,3], 5),
(2, array[2,3,4], 6),
(3, array[3,4,5], 2),
(1, array[7,8,9], 19);

WITH u AS (
SELECT id, unnest(aint) as t FROM a GROUP BY 1,2
),
d AS (
SELECT id, array_agg(distinct t) ar FROM u GROUP BY 1),
v as (
SELECT id, sum(summable_val) AS val
FROM a GROUP BY 1
)
SELECT v.id, v.val, d.ar
FROM v
JOIN d
ON   v.id = d.id;

上面的代码符合我的意图,但问题是我们可以做得更好吗?这个解决方案的主要缺点是它读取和聚合表两次,这对于较大的表可能很麻烦。

对一般问题的一些其他解决方案是避免使用数组列并为每个数组成员聚合“summable”列,然后在聚合中使用array_agg - 但至少现在我想坚持这种阵列方式。

提前感谢任何想法。

1 个答案:

答案 0 :(得分:6)

查询可能会快一点(我猜)但我看不到任何显着的优化:

select a.id, sum(summable_val) val, ar
from
    (select id, array_agg(distinct t) ar 
        from 
        (select id, unnest(aint) as t from a group by 1,2) u
    group by 1) x
    join a on x.id = a.id
group by 1,3