UNION ALL
Je zou kunnen "tegendraaien" met UNION ALL
eerst:
SELECT name, array_agg(c) AS c_arr
FROM (
SELECT name, id, 1 AS rnk, col1 AS c FROM tbl
UNION ALL
SELECT name, id, 2, col2 FROM tbl
ORDER BY name, id, rnk
) sub
GROUP BY 1;
Aangepast om de volgorde van waarden te produceren die u later hebt aangevraagd. De handleiding:
Vetgedrukte nadruk van mij.
LATERAL
subquery
met VALUES
uitdrukking
LATERAL
vereist Postgres 9.3 of later.
SELECT t.name, array_agg(c) AS c_arr
FROM (SELECT * FROM tbl ORDER BY name, id) t
CROSS JOIN LATERAL (VALUES (t.col1), (t.col2)) v(c)
GROUP BY 1;
Zelfde resultaat. Heeft maar een enkele pas over de tafel nodig.
Aangepaste aggregatiefunctie
Of je zou een aangepaste aggregatiefunctie kunnen maken zoals besproken in deze gerelateerde antwoorden:
- Gegevens selecteren in een Postgres-array
- Is er zoiets als een zip()-functie in PostgreSQL die twee arrays combineert?
CREATE AGGREGATE array_agg_mult (anyarray) (
SFUNC = array_cat
, STYPE = anyarray
, INITCOND = '{}'
);
Dan kun je:
SELECT name, array_agg_mult(ARRAY[col1, col2] ORDER BY id) AS c_arr
FROM tbl
GROUP BY 1
ORDER BY 1;
Of, meestal sneller, hoewel niet standaard SQL:
SELECT name, array_agg_mult(ARRAY[col1, col2]) AS c_arr
FROM (SELECT * FROM tbl ORDER BY name, id) t
GROUP BY 1;
De toegevoegde ORDER BY id
(die aan dergelijke geaggregeerde functies kan worden toegevoegd) garandeert het gewenste resultaat:
a | {1,2,3,4}
b | {5,6,7,8}
Of misschien ben je geïnteresseerd in dit alternatief:
SELECT name, array_agg_mult(ARRAY[ARRAY[col1, col2]] ORDER BY id) AS c_arr
FROM tbl
GROUP BY 1
ORDER BY 1;
Die 2-dimensionale arrays produceert:
a | {{1,2},{3,4}}
b | {{5,6},{7,8}}
De laatste kan worden vervangen (en zou moeten zijn, want het is sneller!) met de ingebouwde array_agg()
in Postgres 9.5 of later - met de toegevoegde mogelijkheid om arrays te aggregeren:
SELECT name, array_agg(ARRAY[col1, col2] ORDER BY id) AS c_arr
FROM tbl
GROUP BY 1
ORDER BY 1;
Zelfde resultaat. De handleiding:
Dus niet precies hetzelfde als onze aangepaste aggregatiefunctie array_agg_mult()
;