web-dev-qa-db-fra.com

Postgresql GROUP_CONCAT équivalent?

J'ai une table et j'aimerais tirer une ligne par ID avec les valeurs de champ concaténées.

Dans mon tableau, par exemple, j'ai ceci:

TM67 | 4  | 32556
TM67 | 9  | 98200
TM67 | 72 | 22300
TM99 | 2  | 23009
TM99 | 3  | 11200

Et je voudrais sortir:

TM67 | 4,9,72 | 32556,98200,22300
TM99 | 2,3    | 23009,11200

Dans MySQL, j'ai pu utiliser la fonction d'agrégation GROUP_CONCAT, mais cela ne semble pas fonctionner ici. Existe-t-il un équivalent pour PostgreSQL, ou un autre moyen de réaliser cela?

201
TwixxyKit

C'est probablement un bon point de départ (version 8.4+ uniquement):

SELECT id_field, array_agg(value_field1), array_agg(value_field2)
FROM data_table
GROUP BY id_field

array_agg retourne un tableau, mais vous pouvez le convertir en texte et le modifier au besoin (voir les éclaircissements ci-dessous).

Avant la version 8.4, vous devez le définir vous-même avant de l'utiliser:

CREATE AGGREGATE array_agg (anyelement)
(
    sfunc = array_append,
    stype = anyarray,
    initcond = '{}'
);

(paraphrasé de la documentation PostgreSQL)

Clarifications:

  • Le résultat de la conversion d'un tableau en texte est que la chaîne obtenue commence et se termine par des accolades. Ces accolades doivent être supprimées par une méthode, si elles ne sont pas souhaitées. 
  • La conversion de ANYARRAY en TEXT simule au mieux la sortie CSV, car les éléments contenant des virgules incorporées sont placés entre guillemets dans la sortie au format CSV standard. Ni array_to_string (), ni string_agg () (fonction "group_concat" ajoutée dans 9.1), ne cite des chaînes avec des virgules incorporées, ce qui entraîne un nombre incorrect d'éléments dans la liste résultante.
  • La nouvelle fonction 9.1 string_agg () NE convertit PAS en premier les résultats internes en TEXT. Donc "string_agg (value_field)" générerait une erreur si value_field est un entier. "string_agg (value_field :: text)" serait requis. La méthode array_agg () ne nécessite qu'une conversion après l'agrégation (plutôt qu'une conversion par valeur).
194
Matthew Wood

Depuis 9.0 c'est encore plus simple:

SELECT id, 
       string_agg(some_column, ',')
FROM the_table
GROUP BY id
224
SELECT array_to_string(array(SELECT a FROM b),', ');

Fera aussi bien.

38
genobis

Essayez comme ça:

select field1, array_to_string(array_agg(field2), ',')
from table1
group by field1;
12
max_spy

et la version à utiliser sur le type array :

select
  array_to_string(
    array(select distinct unnest(Zip_codes) from table),
    ', '
);
0
Sławomir Lenart

Ma suggestion dans postgresql

SELECT cpf || ';' || nome || ';' || telefone  
FROM (
      SELECT cpf
            ,nome
            ,STRING_AGG(CONCAT_WS( ';' , DDD_1, TELEFONE_1),';') AS telefone 
      FROM (
            SELECT DISTINCT * 
            FROM temp_bd 
            ORDER BY cpf DESC ) AS y
      GROUP BY 1,2 ) AS x   
0
Lucas Cabral