sql >> Base de Datos >  >> RDS >> PostgreSQL

¿Podemos definir una función GROUP_CONCAT en PostgreSQL?

Hay un string_agg() integrado que hace lo que quieres, pero pides específicamente que se llame group_concat para la compatibilidad con MySQL. Desafortunadamente, string_agg() usa un tipo de datos interno para la acumulación (presumiblemente para evitar copiar todo el búfer en cada apéndice, aunque no he mirado la fuente) y no encontré una manera de declarar un agregado de SQL idéntico a string_agg( ).

Definir la función group_concat() tampoco funcionaría, ya que pg debe ser consciente de que es un agregado, no una función con un agregado oculto dentro, que no funcionaría. Tal función operaría en una fila a la vez:cualquier agregado dentro simplemente agregaría una sola fila y la devolvería sin cambios...

Por lo tanto, este código acumulará los elementos en una matriz, luego agregará los delimitadores "," con array_to_string. Usaré la declaración array_agg() (antes de que se convirtiera en una función integrada) como modelo, y simplemente agregaré una función de finalizador que convertirá la matriz agregada en 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;

Lo bueno es que debería funcionar bien para cualquier tipo, sin problemas, gracias a los tipos genéricos "anyarray" y "anyelement".

Supongo que esto sería más lento que string_agg() si string_agg evita copiar toda la matriz de agregación en cada apéndice. Sin embargo, esto solo debería importar si el número de filas que se agruparán en cada conjunto es grande. En este caso, probablemente puedas dedicar un minuto a editar la consulta SQL;)

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