PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Pouvons-nous définir une fonction GROUP_CONCAT dans PostgreSQL ?

Il existe une fonction intégrée string_agg() qui fait ce que vous voulez, mais vous demandez spécifiquement qu'elle soit nommée group_concat pour la compatibilité MySQL. Malheureusement, string_agg() utilise un type de données interne pour l'accumulation (probablement pour éviter de copier tout le tampon à chaque ajout, je n'ai pas regardé la source cependant) et je n'ai pas trouvé de moyen de déclarer un agrégat SQL identique à string_agg( ).

Définir la fonction group_concat() ne fonctionnerait pas non plus, car pg doit être conscient qu'il s'agit d'un agrégat, et non d'une fonction avec un agrégat caché à l'intérieur, ce qui ne fonctionnerait pas. Une telle fonction fonctionnerait sur une ligne à la fois :tout agrégat à l'intérieur ne ferait qu'agréger une seule ligne et la renverrait inchangée...

Ainsi, ce code accumulera les éléments dans un tableau, puis ajoutera les délimiteurs "," avec array_to_string. J'utiliserai la déclaration array_agg() (avant qu'elle ne devienne intégrée) comme modèle, et j'ajouterai simplement une fonction de finalisation qui convertira le tableau agrégé en texte.

CREATE OR REPLACE FUNCTION _group_concat_finalize(anyarray)
RETURNS text AS $$
    SELECT array_to_string($1,',')
$$ IMMUTABLE LANGUAGE SQL;

CREATE AGGREGATE group_concat(anyelement) (
   SFUNC=array_append,
   STYPE=anyarray,
   FFUNC=_group_concat_finalize,
   INITCOND='{}'
);

SELECT group_concat(x) FROM foo;

La bonne chose est que cela devrait fonctionner correctement pour n'importe quel type, sans tracas, grâce aux types génériques "anyarray" et "anyelement".

Je suppose que ce serait plus lent que string_agg() si string_agg évite effectivement de copier tout le tableau d'agrégation à chaque ajout. Cependant, cela ne devrait avoir d'importance que si le nombre de lignes à regrouper dans chaque ensemble est important. Dans ce cas, vous pouvez probablement passer une minute à éditer la requête SQL;)

http://sqlfiddle.com/#!17/c452d/1