Existuje vestavěná funkce string_agg(), která dělá, co chcete, ale výslovně požadujete, aby se jmenovala group_concat kvůli kompatibilitě s MySQL. Bohužel string_agg() používá pro akumulaci interní datový typ (pravděpodobně proto, abych se vyhnul zkopírování celého bufferu na každém appendu, nepodíval jsem se však na zdroj) a nenašel jsem způsob, jak deklarovat agregaci SQL identickou s string_agg( ).
Nefungovalo by ani definování funkce group_concat(), protože pg si musí být vědom, že jde o agregaci, nikoli o funkci s agregací skrytým uvnitř, což by nefungovalo. Taková funkce by fungovala vždy na jednom řádku:jakýkoli agregát uvnitř by pouze agregoval jeden řádek a vrátil by jej beze změny...
Tento kód tedy shromáždí prvky do pole a poté přidá oddělovače "," pomocí pole_k_řetězci. Jako model použiji deklaraci array_agg() (než se stala vestavěnou) a jednoduše přidám funkci finalizátoru, která převede agregované pole na text.
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;
Pěkné je, že by to mělo fungovat dobře pro jakýkoli typ, bez potíží, díky obecným typům „anyarray“ a „anyelement“.
Předpokládal bych, že by to bylo pomalejší než string_agg(), pokud se string_agg skutečně vyhýbá kopírování celého agregačního pole na každém připojení. To by však mělo záležet pouze v případě, že je počet řádků, které mají být seskupeny do každé sady, velký. V tomto případě pravděpodobně můžete strávit minutu úpravou SQL dotazu;)
http://sqlfiddle.com/#!17/c452d/1