UNION ALL
Vous pouvez "contre-pivoter" avec UNION ALL
d'abord :
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;
Adapté pour produire l'ordre des valeurs que vous avez demandé ultérieurement. Le manuel :
J'insiste sur moi.
LATERAL
sous-requête
avec VALUES
expression
LATERAL
nécessite Postgres 9.3 ou plus tard.
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;
Même résultat. Ne nécessite qu'un seul passage sur la table.
Fonction d'agrégation personnalisée
Ou vous pouvez créer une fonction d'agrégation personnalisée comme indiqué dans ces réponses associées :
- Sélectionner des données dans un Tableau Postgres
- Existe-t-il quelque chose comme une fonction zip() dans PostgreSQL qui combine deux tableaux ?
CREATE AGGREGATE array_agg_mult (anyarray) (
SFUNC = array_cat
, STYPE = anyarray
, INITCOND = '{}'
);
Ensuite, vous pouvez :
SELECT name, array_agg_mult(ARRAY[col1, col2] ORDER BY id) AS c_arr
FROM tbl
GROUP BY 1
ORDER BY 1;
Ou, généralement plus rapide, bien qu'il ne s'agisse pas de 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;
L'identifiant ORDER BY id
ajouté (qui peut être ajouté à ces fonctions d'agrégation) garantit le résultat souhaité :
a | {1,2,3,4}
b | {5,6,7,8}
Ou vous pourriez être intéressé par cette alternative :
SELECT name, array_agg_mult(ARRAY[ARRAY[col1, col2]] ORDER BY id) AS c_arr
FROM tbl
GROUP BY 1
ORDER BY 1;
Qui produit des tableaux à 2 dimensions :
a | {{1,2},{3,4}}
b | {{5,6},{7,8}}
Le dernier peut être remplacé (et devrait l'être, car il est plus rapide !) par le array_agg()
intégré dans Postgres 9.5 ou version ultérieure - avec sa capacité supplémentaire d'agrégation de tableaux :
SELECT name, array_agg(ARRAY[col1, col2] ORDER BY id) AS c_arr
FROM tbl
GROUP BY 1
ORDER BY 1;
Même résultat. Le manuel :
Donc pas exactement la même chose que notre fonction d'agrégation personnalisée array_agg_mult()
;