Istnieje wbudowane string_agg(), które robi to, co chcesz, ale specjalnie prosisz o nazwę group_concat dla zgodności z MySQL. Niestety, string_agg() używa wewnętrznego typu danych do akumulacji (prawdopodobnie w celu uniknięcia kopiowania całego bufora przy każdym dodawaniu, jednak nie zajrzałem do źródła) i nie znalazłem sposobu, aby zadeklarować agregację SQL identyczną z string_agg( ).
Zdefiniowanie funkcji group_concat() również by nie zadziałało, ponieważ należy uświadomić pg, że jest to agregat, a nie funkcja z ukrytym agregatem, która nie zadziała. Taka funkcja działałaby na jednym wierszu na raz:każdy agregat wewnątrz agregowałby tylko jeden wiersz i zwracał go bez zmian...
Tak więc ten kod zgromadzi elementy w tablicy, a następnie doda ograniczniki "," z array_to_string. Użyję deklaracji array_agg() (zanim stała się wbudowaną) jako modelu i po prostu dodam funkcję finalizatora, która przekonwertuje zagregowaną tablicę na tekst.
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;
Fajną rzeczą jest to, że powinien działać dobrze dla każdego typu, bez kłopotów, dzięki typom ogólnym "anyarray" i "anyelement".
Zakładałbym, że byłoby to wolniejsze niż string_agg(), jeśli string_agg rzeczywiście unika kopiowania całej tablicy agregacji przy każdym dołączaniu. Powinno to mieć jednak znaczenie tylko wtedy, gdy liczba wierszy do zgrupowania w każdym zestawie jest duża. W takim przypadku prawdopodobnie będziesz mógł poświęcić minutę na edycję zapytania SQL;)
http://sqlfiddle.com/#!17/c452d/1