成对数组和聚合函数?

Fra*_*eil 8 postgresql aggregate-functions

我有一个数组作为一列的表,我想将数组元素加在一起:

> create table regres(a int[] not null);
> insert into regres values ('{1,2,3}'), ('{9, 12, 13}');
> select * from regres;
     a
-----------
 {1,2,3}
 {9,12,13}
Run Code Online (Sandbox Code Playgroud)

我希望结果如下:

{10, 14, 16}
Run Code Online (Sandbox Code Playgroud)

那就是:{1 + 9, 2 + 12, 3 + 13}.

这样的功能在某处已经存在吗?插入扩展看起来是一个很好的候选者,但这样的功能尚不存在.

预计数组的长度在24到31个元素之间,所有元素都是NOT NULL,并且数组本身也将是NOT NULL.所有元素都是基本的int.每个聚合将有两行以上.在查询中,所有数组都将具有相同数量的元素.不同的查询将具有不同数量的元素.

我的实现目标是:x86_64-unknown-linux-gnu上的PostgreSQL 9.1.13,由gcc编译(Ubuntu/Linaro 4.6.3-1ubuntu5)4.6.3,64位

Erw*_*ter 13

一般的解决方案中的Postgres 9.3+为任何数量的阵列具有任意数量的元件.
单个元素或整个数组也可以为NULL:

SELECT ARRAY (
   SELECT sum(arr[rn])
   FROM  tbl t
       , generate_subscripts(t.arr, 1) AS rn
   GROUP BY rn
   ORDER BY rn
   );
Run Code Online (Sandbox Code Playgroud)

这使用了隐含的LATERAL JOIN(Postgres 9.3+).
使用您的示例值:

SELECT ARRAY (
   SELECT sum(arr[rn])
   FROM  (
      VALUES
        ('{1,2,3}'::int[])
       ,('{9,12,13}')
      ) t(arr)
    , generate_subscripts(t.arr, 1) AS rn
   GROUP BY rn
   ORDER BY rn
   );
Run Code Online (Sandbox Code Playgroud)

非平凡的例子:

SELECT ARRAY (
   SELECT sum(arr[rn])
   FROM  (
      VALUES
        ('{1,2,3}'::int[])
       ,('{9,12,13}')
       ,('{1,1,1, 33}')
       ,('{NULL,NULL}')
       ,(NULL)
      ) t(arr)
    , generate_subscripts(t.arr, 1) AS rn
   GROUP BY rn
   ORDER BY rn
   );
Run Code Online (Sandbox Code Playgroud)

更简单的使用9.4+ WITH ORDINALITY

SELECT ARRAY (
   SELECT sum(elem)
   FROM  tbl t
       , unnest(t.arr) WITH ORDINALITY x(elem, rn)
   GROUP BY rn
   ORDER BY rn
   )
Run Code Online (Sandbox Code Playgroud)

Postgres 9.1

SELECT ARRAY (
   SELECT sum(arr[rn])
   FROM  (
      SELECT arr, generate_subscripts(arr, 1) AS rn
      FROM   tbl t
      ) sub
   GROUP BY rn
   ORDER BY rn
   );
Run Code Online (Sandbox Code Playgroud)

同样适用于更高版本,但列表中的set-returns函数SELECT不是标准SQL,而且有些人不赞成.因此,使用上述替代品与当前的Postgres.

SQL小提琴.

相关答案以及更多解释: