A common solution in Postgres 9.3 + for any number of arrays with any number of elements.
Individual elements or the entire array can also be NULL:
SELECT ARRAY ( SELECT sum(arr[rn]) FROM tbl t , generate_subscripts(t.arr, 1) AS rn GROUP BY rn ORDER BY rn );
This uses an implicit LATERAL JOIN (Postgres 9.3+).
With your 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 );
Nontrivial 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 )
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 thing works in later versions, but the set-return functions in the SELECT list SELECT not standard SQL and frown on someone. Therefore, use the above alternatives with current Postgres.
SQL Fiddle
Related answers with lots of explanation: