Función GROUP_CONCAT de MySQL

MySQL logoDescubrí 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:

  1. Editando el archivo de configuración my.cnf y modificando la variable:
    group_concat_max_len=4096
  2. Ejecutando esta orden antes de realizar la consulta:
    SET GLOBAL group_concat_max_len=4096

Fuentes – Syntax ErrorMySQL Performance Blog (mirar también los comentarios)

23 comentarios en “Función GROUP_CONCAT de MySQL

  1. 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

  2. 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!!!!!

  3. Interesante Función buscaba algo así para no tener que realizar una segunda consulta :)

    gracias!

  4. Pingback: MySQL | Annotary
  5. Que aporte mas significativo. sabia que esa función tenia un limite pero no sabia como solucionarlo.

    Gracias!!

  6. Estaba ocupando una libreria para exportar a un archivo y necesitaba que me devolviera todo la consulta SLQ justo con el GROUP_CONCAT sale como lo necesitaba.

    Muy buen aporte, al explicar el codigo me sirvio mucho ya que lo edite para mi necesidad y funciono al segundo intento.

    Gracias!! (La libreria no tenia la documentación >.<)

  7. holaa, use esta funcion para mostrarla en un tabla php, pero el campo que concateno no muestra en la tabla php, extraigo los campos de la consulta con mysql_etch_array, como puedo procesar ese valor devuelto por group_concat en php ????

  8. con la funcion explode como puedo trabajar para poder obtener la cadena concatenada, al extraerlo con mysql_fetch_array este campo esta en blanco,

  9. Hola, excelente explicación.

    El único problema es q si yo hago un GROUP_CONCAT de ids, el sql me retorna un [BLOB – 7B] o cosas así, q se puede hacer??

  10. jajajaja ya encontré como miren!!!

    CONVERT(GROUP_CONCAT(r.id) USING utf8)

    ahora tengo es un lío con las tildes :(

  11. Saludos.

    Alguien ha tenido la necesidad de pasar los valores de este campo en una condición como
    Where campo in (Valores del Concat)

    Esto porque los valores que regresa son algo así (‘1,2,3′) y para pasarlos debe ser algo así como (1,2,3).

    Si alguien sabe como resolver esto se os voy a agradecer infinitamente.

    Gracias.

  12. Muchas gracias por la información, la explicación mediante ejemplos que hiciste, es buenísima.

    Saludos

  13. La descubrí el año pasado trabajando con Tags noticias, similar al ejemplo que aquí mencionás. Ahora la he implementado para recolectar distintas traducciones al español, de un vocablo escrito en inglés.

    Saludos,

  14. Como puedo contar la cantidad de palabras separadas por coma dentro de un campo en mysql, ejemplo.

    nombre apellido
    ———————————————–|—————————
    pedro,juan,diego,marta,alejandra | gonzalez,perez
    —————————————————————————–

    En el campo nombre hay 5 palabras .

    Por favor necesito esto porque debo ordenar los resultado según cantidad de palabras separadas por coma .

    Gracias.ñ

  15. Muchas gracias!!

    Ahora ya puedo salir tranquilo del trabajo, era la función exacta para terminar la consulta que requería.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *

Puedes usar las siguientes etiquetas y atributos HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>