问题
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