¿Puedo concatenar múltiples filas MySQL en un campo?

1214

Usando MySQL, puedo hacer algo como:

SELECT hobbies FROM peoples_hobbies WHERE person_id = 5;

Mi salida:

shopping
fishing
coding

pero en cambio solo quiero 1 fila, 1 col:

Rendimiento esperado:

shopping, fishing, coding

La razón es que selecciono varios valores de varias tablas y, después de todas las uniones, tengo muchas más filas de las que quisiera.

He buscado una función en MySQL Doc y no se parece a la CONCATo CONCAT_WSlas funciones de aceptar conjuntos de resultados.

Entonces, ¿alguien aquí sabe cómo hacer esto?

Dean Rather
fuente
99
Acabo de escribir una pequeña demostración sobre cómo usar group_concat que podría serle útil: giombetti.com/2013/06/06/mysql-group_concat
Marc Giombetti

Respuestas:

1739

Puedes usar GROUP_CONCAT:

SELECT person_id, GROUP_CONCAT(hobbies SEPARATOR ', ')
FROM peoples_hobbies
GROUP BY person_id;

Como dijo Ludwig en su comentario, puede agregar el DISTINCToperador para evitar duplicados:

SELECT person_id, GROUP_CONCAT(DISTINCT hobbies SEPARATOR ', ')
FROM peoples_hobbies 
GROUP BY person_id;

Como Jan declaró en su comentario, también puede ordenar los valores antes de implosionarlos usando ORDER BY:

SELECT person_id, GROUP_CONCAT(hobbies ORDER BY hobbies ASC SEPARATOR ', ')
FROM peoples_hobbies
GROUP BY person_id;

Como dijo Dag en su comentario, hay un límite de 1024 bytes en el resultado. Para resolver esto, ejecute esta consulta antes de su consulta:

SET group_concat_max_len = 2048;

Por supuesto, puede cambiar 2048según sus necesidades. Para calcular y asignar el valor:

SET group_concat_max_len = CAST(
    (SELECT SUM(LENGTH(hobbies)) + COUNT(*) * LENGTH(', ')
    FROM peoples_hobbies 
    GROUP BY person_id)
    AS UNSIGNED
);
che
fuente
155
Solo tenga en cuenta la limitación de 1024 bytes en la columna resultante (vea el parámetro group_concat_max_len )
Dag
81
Y agregando el DISTINCTparámetro, no obtendrá ningún doble. ... GROUP_CONCAT(DISTINCT hobbies)
Ludwig
3
Mi necesidad era obtener TODOS los datos de una columna. No use la cláusula GROUP BY para hacer esto. Ejemplo: SELECT GROUP_CONCAT (correos electrónicos SEPARATOR ',') DE usuarios;
Jonathan Bergeron
1
Gracias, no sabía que había un límite de longitud de concat grupal. Necesitaba eso para sortear una lista de monstruos que generé.
Patrick
99
Si desea ordenar pasatiempos en el uso de la cadena implosionada resultante:SELECT person_id, GROUP_CONCAT(hobbies ORDER BY hobbies ASC SEPARATOR ', ') FROM peoples_hobbies GROUP BY person_id
Jan
106

Eche un vistazo a GROUP_CONCATsi su versión de MySQL (4.1) lo admite. Consulte la documentación para más detalles.

Se vería algo así como:

  SELECT GROUP_CONCAT(hobbies SEPARATOR ', ') 
  FROM peoples_hobbies 
  WHERE person_id = 5 
  GROUP BY 'all';
lpfavreau
fuente
11
Creo que eso group by 'all'no es necesario (además no deseado), porque esto asigna a todas las filas una cadena ally luego compara cadenas entre estas filas. Estoy en lo cierto?
Krzysiek
74

Sintaxis alternativa para concatenar múltiples filas individuales

ADVERTENCIA: Esta publicación te dará hambre.

Dado:

Me encontré con ganas de seleccionar múltiples filas individuales, en lugar de un grupo, y concatenar en un determinado campo.

Digamos que tiene una tabla de identificadores de productos y sus nombres y precios:

+------------+--------------------+-------+
| product_id | name               | price |
+------------+--------------------+-------+
|         13 | Double Double      |     5 |
|         14 | Neapolitan Shake   |     2 |
|         15 | Animal Style Fries |     3 |
|         16 | Root Beer          |     2 |
|         17 | Lame T-Shirt       |    15 |
+------------+--------------------+-------+

Luego, tienes un ajax sofisticado que enumera a estos cachorros como casillas de verificación.

Tu usuario de hipopótamo hambriento selecciona 13, 15, 16. No hay postre para ella hoy ...

Encontrar:

Una forma de resumir el pedido de su usuario en una línea, con mysql puro.

Solución:

Usar GROUP_CONCATcon la INcláusula :

mysql> SELECT GROUP_CONCAT(name SEPARATOR ' + ') AS order_summary FROM product WHERE product_id IN (13, 15, 16);

Qué salidas:

+------------------------------------------------+
| order_summary                                  |
+------------------------------------------------+
| Double Double + Animal Style Fries + Root Beer |
+------------------------------------------------+

Solución de bonificación:

Si también desea el precio total, agregue SUM():

mysql> SELECT GROUP_CONCAT(name SEPARATOR ' + ') AS order_summary, SUM(price) AS total FROM product WHERE product_id IN (13, 15, 16);
+------------------------------------------------+-------+
| order_summary                                  | total |
+------------------------------------------------+-------+
| Double Double + Animal Style Fries + Root Beer |    10 |
+------------------------------------------------+-------+

PD: Disculpas si no tienes un In-N-Out cerca ...

pie de codo
fuente
11
Aunque esta es una buena respuesta, suena más como publicidad que como una simple respuesta. Sigue siendo una buena respuesta bien formateada.
FliiFe
1
¿Puedo obtener ayuda stackoverflow.com/q/60278898/11697039 @elbowlobstercowstand
zus
39

Puede cambiar la longitud máxima del GROUP_CONCATvalor configurando el group_concat_max_lenparámetro.

Ver detalles en la documentación de MySQL .

pau.moreno
fuente
25

En mi caso, tenía una fila de ID, y era necesario convertirlo en char, de lo contrario, el resultado se codificó en formato binario:

SELECT CAST(GROUP_CONCAT(field SEPARATOR ',') AS CHAR) FROM table
Fedir RYKHTIK
fuente
1
¡Gracias! Sin CASTtener valores como [BLOB - 14 Bytes]en el resultado!
Mel_T
1
¿Puedo obtener ayuda stackoverflow.com/q/60278898/11697039 @Fedir RYKHTIK
zus
16

Utilice la variable de sesión MySQL (5.6.13) y el operador de asignación como el siguiente

SELECT @logmsg := CONCAT_ws(',',@logmsg,items) FROM temp_SplitFields a;

entonces puedes conseguir

test1,test11
Shen liang
fuente
2
¿Es más rápido que GROUP_CONCAT?
jave.web
1
Probé esto en PHPMyAdmin con el servidor MySQL v5.6.17 en una columna de descripción (varchar (50)) en una tabla de prueba , pero devuelve un campo BLOB para cada registro:SELECT @logmsg := CONCAT_ws(',',@logmsg,description) from test
Jan
14

Tuve una consulta más complicada y descubrí que tenía que usarla GROUP_CONCATen una consulta externa para que funcionara:

Consulta original:

SELECT DISTINCT userID 
FROM event GROUP BY userID 
HAVING count(distinct(cohort))=2);

Imploded:

SELECT GROUP_CONCAT(sub.userID SEPARATOR ', ') 
FROM (SELECT DISTINCT userID FROM event 
GROUP BY userID HAVING count(distinct(cohort))=2) as sub;

Espero que esto pueda ayudar a alguien.

Alex Bowyer
fuente
9

Para alguien que mira aquí cómo usar GROUP_CONCATcon subconsulta: publicar este ejemplo

SELECT i.*,
(SELECT GROUP_CONCAT(userid) FROM favourites f WHERE f.itemid = i.id) AS idlist
FROM items i
WHERE i.id = $someid

Por GROUP_CONCATlo tanto, debe usarse dentro de la subconsulta, no envolviéndola.

Oleg Abrazhaev
fuente
1
Esto era exactamente lo que estaba buscando
bumerang
7

Prueba esto:

DECLARE @Hobbies NVARCHAR(200) = ' '

SELECT @Hobbies = @Hobbies + hobbies + ',' FROM peoples_hobbies WHERE person_id = 5;
thejustv
fuente
2
Esto es lo que obtuve: 'Tipo de declaración no reconocida. (cerca de "DECLARE" en la posición 0) '
Istiaque Ahmed
1

tenemos dos formas de concatenar columnas en MySql

select concat(hobbies) as `Hobbies` from people_hobbies where 1

O

select group_concat(hobbies) as `Hobbies` from people_hobbies where 1
raghavendra
fuente