UNION ALL
Sie könnten mit UNION ALL
"gegenschwenken". zuerst:
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;
Angepasst, um die Reihenfolge der Werte zu erzeugen, die Sie später angefordert haben. Das Handbuch:
Fettdruck von mir.
LATERAL
Unterabfrage
mit VALUES
Ausdruck
LATERAL
erfordert Postgres 9.3 oder später.
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;
Gleiches Ergebnis. Benötigt nur einen einzigen Durchgang über den Tisch.
Benutzerdefinierte Aggregatfunktion
Oder Sie könnten eine benutzerdefinierte Aggregatfunktion erstellen, wie in diesen verwandten Antworten beschrieben:
- Auswahl von Daten in a Postgres-Array
- Gibt es in PostgreSQL so etwas wie eine zip()-Funktion, die zwei Arrays kombiniert?
CREATE AGGREGATE array_agg_mult (anyarray) (
SFUNC = array_cat
, STYPE = anyarray
, INITCOND = '{}'
);
Dann können Sie:
SELECT name, array_agg_mult(ARRAY[col1, col2] ORDER BY id) AS c_arr
FROM tbl
GROUP BY 1
ORDER BY 1;
Oder, normalerweise schneller, aber kein 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;
Die hinzugefügte ORDER BY id
(die an solche Aggregatfunktionen angehängt werden können) garantiert Ihr gewünschtes Ergebnis:
a | {1,2,3,4}
b | {5,6,7,8}
Oder Sie könnten an dieser Alternative interessiert sein:
SELECT name, array_agg_mult(ARRAY[ARRAY[col1, col2]] ORDER BY id) AS c_arr
FROM tbl
GROUP BY 1
ORDER BY 1;
Was zweidimensionale Arrays erzeugt:
a | {{1,2},{3,4}}
b | {{5,6},{7,8}}
Das letzte kann durch das eingebaute array_agg()
ersetzt werden (und sollte es auch sein, da es schneller ist!). in Postgres 9.5 oder höher - mit der zusätzlichen Fähigkeit, Arrays zu aggregieren:
SELECT name, array_agg(ARRAY[col1, col2] ORDER BY id) AS c_arr
FROM tbl
GROUP BY 1
ORDER BY 1;
Gleiches Ergebnis. Das Handbuch:
Also nicht genau dasselbe wie unsere benutzerdefinierte Aggregatfunktion array_agg_mult()
;