Función GROUP_CONCAT de MySQL
In: mysql
19 oct 2009
Descubrí el otro día la función GROUP_CONCAT, que puede ser muy útil cuando hacemos consultas a MySQL donde usamos el GROUP BY. Sirve para concatenar con un separador, todos los registros afectados por un GROUP BY en un solo campo de salida. Lo mejor es explicarlo con un ejemplo.
Tenemos dos tablas, Contenidos y Categorías (o cualquier relación típica de 1:N o N:N). El objetivo es sacar todos los contenidos, y en cada registro de contenidos, las categorías de cada uno de ellos.
Si hiciéramos una consulta en que relacionamos las tablas, hicieramos el GROUP BY, y pidieramos los campos nombre_contenido y nombre_categoria, solamente retornaría el nombre de una categoría, la primera que encuentre:
SELECT nombre_contenido, nombre_categoria FROM contenidos INNER JOIN categorias_contenidos USING (id_contenido) INNER JOIN categorias USING (id_categoria) GROUP BY id_contenido
Pero con la función GROUP_CONCAT, todas las Categorías que se ven agrupadas por el GROUP BY, serán concatenadas en un campo, con una coma como separador.
SELECT nombre_contenido, GROUP_CONCAT(nombre_categoria) FROM contenidos INNER JOIN categorias_contenidos USING (id_contenido) INNER JOIN categorias USING (id_categoria) GROUP BY id_contenido
La función GROUP_CONCAT solo tiene un parámetro, que es una expresión. Básicamente puede ser el nombre de la columna a concatenar. Pero permite tres personalizaciones, según nuestras necesidades:
- Utilizar DISTINCT, para evitar las repeticiones
- Añadir un ORDER BY, para decidir el orden de concatenación del campo
- Definir con SEPARATOR el separador a utilizar para separar los campos (por defecto, el separador es una coma)
Pongo un ejemplo completo con todas las funcionalidades de GROUP_CONCAT, así no tendremos repeticiones de las categorías, estarán ordenadas alfabéticamente y separadas por un guión:
SELECT nombre_contenido, GROUP_CONCAT(DISTINCT nombre_categoria ORDER BY nombre_categoria ASC SEPARATOR '-') FROM contenidos INNER JOIN categorias_contenidos USING (id_contenido) INNER JOIN categorias USING (id_categoria) GROUP BY id_contenido
Una vez recibido el registro, podemos convertir este campo concatenado en un array, simplemente utilizando la función explode de PHP.
Actualización: A través del comentario de Daniel, me entero que la función tiene un límite de 1024 caracteres, incluidos los separadores. En un ejemplo que he visto, he leído que en una consulta en que la función GROUP_CONCAT tenía que devolver del 1 al 20.000 separados por comas, solo devolvía hasta el 283; los números cuadran de la siguiente manera:
- Del 1 al 9, van 9 caracteres
- Del 10 al 99, van 90*2= 180 caracteres
- Del 100 al 283, van 184*3= 552 caracteres
- Más las 283 comas, que son 283 carácteres más
- TOTAL = 9 + 180 + 552 + 283 = 1024 caracteres.
Pero esto no es un inconveniente para utilizar la función GROUP_CONCAT. Este límite se puede modificar a nuestro gusto, de las dos maneras siguientes:
- Editando el archivo de configuración my.cnf y modificando la variable:
group_concat_max_len=4096
- Ejecutando esta orden antes de realizar la consulta:
SET GLOBAL group_concat_max_len=4096
Fuentes – Syntax Error y MySQL Performance Blog (mirar también los comentarios)
Entradas relacionadas:

4 Comentarios en Función GROUP_CONCAT de MySQL
Daniel
19 octubre 2009 a las 14:46
Es una gran función.
Para tener en cuenta: Tiene un límite de 1024 caracteres. Si el resultado es mayor mysql lo trunca. De todas formas, el valor puede ser modificado desde la configuración cambiando la variable group_concat_max_len
Saludos
Miguel Angel
14 marzo 2012 a las 23:07
Gracias por este Post!!!!!!
Estaba utilizando justamente esta función en una consulta, que por independiente el group_concat me funcionaba bien para un ID determinado pero cuando lo metía dentro de la consulta general, me generaba multiples filas en la subconsulta. He cambiado el planteamiento al tuyo y me ha funcionado a la primera!!!!!
Muchas gracias!!!!!
desarrollo
03 abril 2012 a las 17:36
muchas gracias me fue muy util, te diera 10 puntos.
Pibe
09 abril 2012 a las 20:02
fuck this shit!