MySQL tiene un GROUP_CONCAT()
función que nos permite devolver columnas de una consulta como una lista delimitada.
Devuelve un resultado de cadena con el concatenado no NULL
valores de un grupo.
Sintaxis
La sintaxis es así:
GROUP_CONCAT([DISTINCT] expr [,expr ...]
[ORDER BY {unsigned_integer | col_name | expr}
[ASC | DESC] [,col_name ...]]
[SEPARATOR str_val])
Ejemplo
Supongamos que ejecutamos la siguiente consulta:
SELECT PetName
FROM Pets;
Y obtenemos el siguiente resultado:
+---------+ | PetName | +---------+ | Fluffy | | Fetch | | Scratch | | Wag | | Tweet | | Fluffy | | Bark | | Meow | +---------+ 8 rows in set (0.00 sec)
Podemos usar GROUP_CONCAT()
para devolver todas esas filas como una lista delimitada.
Para hacer esto, necesitamos pasar el PetName
columna como argumento para GROUP_CONCAT()
función:
SELECT GROUP_CONCAT(PetName)
FROM Pets;
Resultado:
+-------------------------------------------------+ | GROUP_CONCAT(PetName) | +-------------------------------------------------+ | Fluffy,Fetch,Scratch,Wag,Tweet,Fluffy,Bark,Meow | +-------------------------------------------------+ 1 row in set (0.01 sec)
Pedidos
Podemos usar el ORDER BY
cláusula para ordenar la salida de esta función:
SELECT GROUP_CONCAT(PetName ORDER BY PetName ASC)
FROM Pets;
Resultado:
Bark,Fetch,Fluffy,Fluffy,Meow,Scratch,Tweet,Wag
Tenga en cuenta que esto solo ordena la salida de GROUP_CONCAT()
función:es completamente independiente de cualquier orden aplicado a SELECT
declaración en sí.
El DISTINCT
Cláusula
Podemos usar el DISTINCT
cláusula para devolver valores únicos. En otras palabras, si hay valores duplicados, solo se devuelve una ocurrencia:
SELECT GROUP_CONCAT(DISTINCT PetName ORDER BY PetName ASC)
FROM Pets;
Resultado:
Bark,Fetch,Fluffy,Meow,Scratch,Tweet,Wag
En este caso, Fluffy
solo aparece una vez. Cuando lo ejecutamos sin DISTINCT
cláusula, Fluffy
aparece dos veces.
Cambiar el separador
De forma predeterminada, la lista utiliza la coma como delimitador. Pero podemos cambiar esto si queremos:
SELECT GROUP_CONCAT(PetName SEPARATOR '-')
FROM Pets;
Resultado:
Fluffy-Fetch-Scratch-Wag-Tweet-Fluffy-Bark-Meow
Incluso podemos usar una cadena vacía para eliminar todos los separadores (para que los valores se concatenen):
SELECT GROUP_CONCAT(PetName SEPARATOR '')
FROM Pets;
Y obtenemos el siguiente resultado:
FluffyFetchScratchWagTweetFluffyBarkMeow
Resultados de consultas agrupados
Podemos incluir GROUP_CONCAT()
en una consulta con un GROUP BY
cláusula para lograr un resultado como este:
SELECT
PetTypeId,
GROUP_CONCAT(PetName ORDER BY PetName ASC)
FROM Pets
GROUP BY PetTypeId
ORDER BY PetTypeId;
Resultado:
+-----------+--------------------------------------------+ | PetTypeId | GROUP_CONCAT(PetName ORDER BY PetName ASC) | +-----------+--------------------------------------------+ | 1 | Tweet | | 2 | Fluffy,Meow,Scratch | | 3 | Bark,Fetch,Fluffy,Wag | +-----------+--------------------------------------------+
En mi base de datos, los nombres reales de los tipos de mascotas están en otra tabla llamada PetTypes
. Por lo tanto, podríamos ejecutar un INNER JOIN
en PetTypes
tabla para obtener los nombres reales de los tipos de mascotas:
SELECT
pt.PetType,
GROUP_CONCAT(p.PetName ORDER BY p.PetName ASC)
FROM Pets p
INNER JOIN PetTypes pt ON
p.PetTypeId = pt.PetTypeId
GROUP BY pt.PetType
ORDER BY pt.PetType ASC;
Resultado:
+---------+------------------------------------------------+ | PetType | GROUP_CONCAT(p.PetName ORDER BY p.PetName ASC) | +---------+------------------------------------------------+ | Bird | Tweet | | Cat | Fluffy,Meow,Scratch | | Dog | Bark,Fetch,Fluffy,Wag | +---------+------------------------------------------------+
Limitaciones de longitud
GROUP_CONCAT()
La salida se trunca a la longitud máxima dada por group_concat_max_len
variable del sistema, que tiene un valor predeterminado de 1024
. El valor se puede establecer más alto, aunque la longitud máxima efectiva del valor de retorno está restringida por el valor de max_allowed_packet
.
Puede verificar el valor actual de esta manera:
SHOW VARIABLES LIKE '%group_concat%';
La sintaxis para cambiar este valor es la siguiente:
SET [GLOBAL | SESSION] group_concat_max_len = val;
Donde val
es un entero sin signo.