Pairwise array sum aggregate function?

大城市里の小女人 提交于 2019-12-20 21:01:48

问题


I have a table with arrays as one column, and I want to sum the array elements together:

> 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}

I want the result to be:

{10, 14, 16}

that is: {1 + 9, 2 + 12, 3 + 13}.

Does such a function already exist somewhere? The intagg extension looked like a good candidate, but such a function does not already exist.

The arrays are expected to be between 24 and 31 elements in length, all elements are NOT NULL, and the arrays themselves will also always be NOT NULL. All elements are basic int. There will be more than two rows per aggregate. All arrays will have the same number of elements, in a query. Different queries will have different number of elements.

My implementation target is: PostgreSQL 9.1.13 on x86_64-unknown-linux-gnu, compiled by gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3, 64-bit


回答1:


A general solution in Postgres 9.3+ for any number of arrays with any number of elements.
Individual elements or the the whole array can be NULL, too:

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

This makes use of an implicit LATERAL JOIN (Postgres 9.3+).
With your example values:

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
   );

Non-trivial example:

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
   );

Simpler in 9.4+ using WITH ORDINALITY

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

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
   );

The same works in later versions, but set-returning functions in the SELECT list are not standard SQL and frowned upon by some. So use above alternatives with current Postgres.

SQL Fiddle.

Related answers with more explanation:

  • PostgreSQL unnest() with element number
  • Is there something like a zip() function in PostgreSQL that combines two arrays?



回答2:


If you need better performances and can install Postgres extensions, the agg_for_vecs C extension provides a vec_to_sum function that should meet your need. It also offers various aggregate functions like min, max, avg, and var_samp that operate on arrays instead of scalars.



来源:https://stackoverflow.com/questions/24997131/pairwise-array-sum-aggregate-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!