UNION ALL
Du kan "mod-pivot" med UNION ALL
først:
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;
Tilpasset til at producere den rækkefølge af værdier, du senere anmodede om. Manualen:
Fed fremhævelse mine.
LATERAL
underforespørgsel
med VALUES
udtryk
LATERAL
kræver Postgres 9.3 eller senere.
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;
Samme resultat. Behøver kun en enkelt gang over bordet.
Tilpasset aggregatfunktion
Eller du kan oprette en tilpasset aggregeret funktion som beskrevet i disse relaterede svar:
- Valg af data i en Postgres-array
- Er der noget som en zip()-funktion i PostgreSQL, der kombinerer to arrays?
CREATE AGGREGATE array_agg_mult (anyarray) (
SFUNC = array_cat
, STYPE = anyarray
, INITCOND = '{}'
);
Så kan du:
SELECT name, array_agg_mult(ARRAY[col1, col2] ORDER BY id) AS c_arr
FROM tbl
GROUP BY 1
ORDER BY 1;
Eller, typisk hurtigere, mens det ikke er standard SQL:
SELECT name, array_agg_mult(ARRAY[col1, col2]) AS c_arr
FROM (SELECT * FROM tbl ORDER BY name, id) t
GROUP BY 1;
Det tilføjede ORDER BY id
(som kan føjes til sådanne samlede funktioner) garanterer dit ønskede resultat:
a | {1,2,3,4}
b | {5,6,7,8}
Eller du er måske interesseret i dette alternativ:
SELECT name, array_agg_mult(ARRAY[ARRAY[col1, col2]] ORDER BY id) AS c_arr
FROM tbl
GROUP BY 1
ORDER BY 1;
Som producerer 2-dimensionelle arrays:
a | {{1,2},{3,4}}
b | {{5,6},{7,8}}
Den sidste kan erstattes (og bør være, da den er hurtigere!) med den indbyggede array_agg()
i Postgres 9.5 eller senere - med dens tilføjede evne til at aggregere arrays:
SELECT name, array_agg(ARRAY[col1, col2] ORDER BY id) AS c_arr
FROM tbl
GROUP BY 1
ORDER BY 1;
Samme resultat. Manualen:
Så ikke helt det samme som vores tilpassede aggregerede funktion array_agg_mult()
;