web-dev-qa-db-fra.com

Comment agréger deux colonnes PostgreSQL dans un tableau séparé par des crochets

Je voudrais concaténer deux colonnes à l'aide d'une requête de regroupement résultant en un tableau séparé par des crochets. Je sais que cette question est liée à la question this , mais comme d'habitude, mon cas d'utilisation est un peu différent.

Un exemple simple (aussi comme SQL Fiddle ). Actuellement, ma requête renvoie ce qui suit:

ID  X   Y
3   0.5 2.71
3   1.0 2.50
3   1.5 2.33
6   0.5 2.73
6   1.5 2.77

Mais là où je voudrais concaténer/agréger les colonnes X/Y pour obtenir ce qui suit:

ID  XY
3   [[0.5,2.71],[1.0,2.50],[1.5,2.33]]
6   [[0.5,2.73],[1.5,2.77]]

Actuellement, j'ai essayé de concaténer les colonnes en une comme suit:

SELECT "ID",concat_ws(', ',"X", "Y") as XY FROM Table1;

Qui retourne:

ID  xy
3   0.5, 2.71
3   1, 2.50
3   1.5, 2.33
6   0.5, 2.73

Et utilisé array_agg():

SELECT "ID",array_to_string(array_agg("X"),',') AS XY
FROM Table1
GROUP BY "ID";

Résultant en:

ID  xy
3   0.5,1,1.5
6   0.5

Je sens que je me rapproche, mais un coup de main serait vraiment apprécié.

14
Mattijn

Créez un tableau à partir des deux colonnes, agrégez le tableau:

select id, array_agg(array[x,y])
from the_table
group by id;

Notez que la représentation textuelle par défaut des tableaux utilise des accolades ({..}) pas entre crochets ([..])

18

Dans Postgres 9.5 ou version ultérieure array_agg() prend tableaux en entrée pour permettre la syntaxe simple - fourni par @a_horse :

SELECT id, array_agg(ARRAY[x, y]) AS xy
FROM   Table1
GROUP  BY id;

Dans les anciennes versions , cela n'est pas encore implémenté. Vous pouvez créer votre propre fonction d'agrégation (une fois) pour obtenir le même résultat:

CREATE AGGREGATE array_agg_mult (anyarray)  (
    SFUNC     = array_cat
  , STYPE     = anyarray
  , INITCOND  = '{}'
);

Alors:

SELECT id, array_agg_mult(ARRAY[ARRAY[x,y]]) AS xy  -- note the 2D array
FROM   Table1
GROUP  BY id;

Détails:

Ou vous pouvez concaténer une chaîne:

SELECT id, '[[' || string_agg(concat_ws(',', x, y), '],[') || ']]' AS xy
FROM   Table1
GROUP  BY id;

Produit exactement le résultat souhaité. Une chaîne, pas un tableau.

5
Erwin Brandstetter