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
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
);
SELECT ARRAY (
SELECT sum(elem)
FROM tbl t
, unnest(t.arr) WITH ORDINALITY x(elem, rn)
GROUP BY rn
ORDER BY rn
)
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:
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.