UNION ALL
Potresti "controbattere" con UNION ALL
primo:
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;
Adattato per produrre l'ordine dei valori che hai richiesto in seguito. Il manuale:
Enfasi in grassetto la mia.
LATERAL
sottoquery
con VALUES
espressione
LATERAL
richiede Postgres 9.3 o successivo.
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;
Stesso risultato. Serve solo un passaggio sul tavolo.
Funzione di aggregazione personalizzata
Oppure potresti creare una funzione aggregata personalizzata come discusso in queste risposte correlate:
- Selezionare i dati in un Matrice Postgres
- C'è qualcosa come una funzione zip() in PostgreSQL che combina due array?
CREATE AGGREGATE array_agg_mult (anyarray) (
SFUNC = array_cat
, STYPE = anyarray
, INITCOND = '{}'
);
Quindi puoi:
SELECT name, array_agg_mult(ARRAY[col1, col2] ORDER BY id) AS c_arr
FROM tbl
GROUP BY 1
ORDER BY 1;
Oppure, in genere più veloce, sebbene non SQL standard:
SELECT name, array_agg_mult(ARRAY[col1, col2]) AS c_arr
FROM (SELECT * FROM tbl ORDER BY name, id) t
GROUP BY 1;
Il ORDER BY id
aggiunto (che può essere aggiunto a tali funzioni aggregate) garantisce il risultato desiderato:
a | {1,2,3,4}
b | {5,6,7,8}
Oppure potresti essere interessato a questa alternativa:
SELECT name, array_agg_mult(ARRAY[ARRAY[col1, col2]] ORDER BY id) AS c_arr
FROM tbl
GROUP BY 1
ORDER BY 1;
Che produce array bidimensionali:
a | {{1,2},{3,4}}
b | {{5,6},{7,8}}
L'ultimo può essere sostituito (e dovrebbe esserlo, dato che è più veloce!) con il built-in array_agg()
in Postgres 9.5 o successivo - con la sua capacità aggiuntiva di aggregare gli array:
SELECT name, array_agg(ARRAY[col1, col2] ORDER BY id) AS c_arr
FROM tbl
GROUP BY 1
ORDER BY 1;
Stesso risultato. Il manuale:
Quindi non è esattamente la stessa della nostra funzione di aggregazione personalizzata array_agg_mult()
;