PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Podemos definir uma função GROUP_CONCAT no PostgreSQL?


Existe um string_agg() embutido que faz o que você quer, mas você pede especificamente que seja nomeado group_concat para compatibilidade com MySQL. Infelizmente, string_agg() usa um tipo de dados interno para acumulação (presumivelmente para evitar copiar todo o buffer em cada anexo, mas não olhei a fonte) e não encontrei uma maneira de declarar um agregado SQL idêntico a string_agg( ).

Definir a função group_concat() também não funcionaria, pois pg deve estar ciente de que é uma agregação, não uma função com uma agregação oculta dentro, o que não funcionaria. Tal função operaria em uma linha de cada vez:qualquer agregação dentro agregaria apenas uma única linha e a retornaria inalterada ...

Assim, este código irá acumular os elementos em um array, então adicionar os delimitadores "," com array_to_string. Usarei a declaração array_agg() (antes de se tornar um built-in) como modelo e simplesmente adicionarei uma função finalizadora que converterá a matriz agregada em texto.
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;

O bom é que deve funcionar bem para qualquer tipo, sem problemas, graças aos tipos genéricos "anyarray" e "anyelement".

Eu presumo que isso seria mais lento que string_agg() se string_agg realmente evitar copiar toda a matriz de agregação em cada anexo. Isso deve importar apenas se o número de linhas a serem agrupadas em cada conjunto for grande. Nesse caso, você provavelmente pode gastar um minuto editando a consulta SQL;)

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