¿Cómo concatenar cadenas de un campo de cadena en una consulta 'agrupar por' de PostgreSQL?
Estoy buscando una manera de concatenar las cadenas de un campo dentro de un grupo mediante consulta. Entonces, por ejemplo, tengo una tabla:
IDENTIFICACIÓN | ID DE LA COMPAÑÍA | EMPLEADO |
---|---|---|
1 | 1 | ana |
2 | 1 | Factura |
3 | 2 | Villancico |
4 | 2 | dave |
y quería agrupar por company_id para obtener algo como:
ID DE LA COMPAÑÍA | EMPLEADO |
---|---|
1 | Ana, Bill |
2 | carol, dave |
Hay una función incorporada en MySQL para hacer esto group_concat
PostgreSQL 9.0 o posterior:
Modern Postgres (desde 2010) tiene la string_agg(expression, delimiter)
función que hará exactamente lo que el autor de la pregunta estaba buscando:
SELECT company_id, string_agg(employee, ', ')
FROM mytable
GROUP BY company_id;
Postgres 9 también agregó la capacidad de especificar una ORDER BY
cláusula en cualquier expresión agregada ; de lo contrario, tendrá que ordenar todos sus resultados o lidiar con un orden indefinido. Entonces ahora puedes escribir:
SELECT company_id, string_agg(employee, ', ' ORDER BY employee)
FROM mytable
GROUP BY company_id;
PostgreSQL 8.4.x:
Tenga en cuenta que el soporte para Postgres 8.4 finalizó en 2014 , por lo que probablemente debería actualizar por razones más importantes que la agregación de cadenas.
PostgreSQL 8.4 (en 2009) introdujo la función agregadaarray_agg(expression)
que recopila los valores en una matriz. Luego array_to_string()
se puede utilizar para dar el resultado deseado:
SELECT company_id, array_to_string(array_agg(employee), ', ')
FROM mytable
GROUP BY company_id;
PostgreSQL 8.3.x y anteriores:
Cuando se planteó originalmente esta pregunta, no había una función agregada incorporada para concatenar cadenas. La implementación personalizada más simple ( sugerida por Vajda Gabo en esta publicación de la lista de correotextcat
, entre muchas otras) es usar la función incorporada :
CREATE AGGREGATE textcat_all(
basetype = text,
sfunc = textcat,
stype = text,
initcond = ''
);
Aquí está la CREATE AGGREGATE
documentación.
Esto simplemente pega todas las cuerdas juntas, sin separador. Para poder insertar un "," entre ellos sin tenerlo al final, es posible que desee crear su propia función de concatenación y sustituirla por el "textcat" anterior. Aquí hay uno que armé y probé en 8.3.12:
CREATE FUNCTION commacat(acc text, instr text) RETURNS text AS $$
BEGIN
IF acc IS NULL OR acc = '' THEN
RETURN instr;
ELSE
RETURN acc || ', ' || instr;
END IF;
END;
$$ LANGUAGE plpgsql;
Esta versión generará una coma incluso si el valor de la fila es nulo o está vacío, por lo que obtendrá un resultado como este:
a, b, c, , e, , g
Si prefiere eliminar comas adicionales para generar esto:
a, b, c, e, g
Luego agregue una ELSIF
marca a la función como esta:
CREATE FUNCTION commacat_ignore_nulls(acc text, instr text) RETURNS text AS $$
BEGIN
IF acc IS NULL OR acc = '' THEN
RETURN instr;
ELSIF instr IS NULL OR instr = '' THEN
RETURN acc;
ELSE
RETURN acc || ', ' || instr;
END IF;
END;
$$ LANGUAGE plpgsql;
¿Qué tal si utilizamos las funciones de matriz integradas de Postgres? Al menos en 8.4, esto funciona de inmediato:
SELECT company_id, array_to_string(array_agg(employee), ',')
FROM mytable
GROUP BY company_id;