MariaDB tem um
GROUP_CONCAT()
função que nos permite retornar colunas de uma consulta como uma lista delimitada. Sintaxe
A sintaxe fica assim:
GROUP_CONCAT([DISTINCT] expr [,expr ...]
[ORDER BY {unsigned_integer | col_name | expr}
[ASC | DESC] [,col_name ...]]
[SEPARATOR str_val]
[LIMIT {[offset,] row_count | row_count OFFSET offset}])
Exemplo
Suponha que executemos a seguinte consulta:
SELECT PetName
FROM Pets;
E obtemos o seguinte resultado:
+---------+ | PetName | +---------+ | Fluffy | | Fetch | | Scratch | | Wag | | Tweet | | Fluffy | | Bark | | Meow | +---------+ 8 rows in set (0.001 sec)
Podemos usar
GROUP_CONCAT()
para retornar todas essas linhas como uma lista delimitada. Para conseguir isso, tudo o que precisamos fazer é passar o
PetName
coluna como um argumento para o GROUP_CONCAT()
função:SELECT GROUP_CONCAT(PetName)
FROM Pets;
Resultado:
+-------------------------------------------------+ | GROUP_CONCAT(PetName) | +-------------------------------------------------+ | Fluffy,Fetch,Scratch,Wag,Tweet,Fluffy,Bark,Meow | +-------------------------------------------------+ 1 row in set (0.003 sec)
Pedidos
Podemos usar o
ORDER BY
cláusula para ordenar a saída desta função:SELECT GROUP_CONCAT(PetName ORDER BY PetName DESC)
FROM Pets;
Resultado:
Wag,Tweet,Scratch,Meow,Fluffy,Fluffy,Fetch,Bark
Observe que isso apenas classifica a saída do
GROUP_CONCAT()
função – é completamente independente de qualquer ordenação aplicada ao SELECT
própria declaração. Limitando a saída
Podemos usar o
LIMIT
cláusula para limitar quantos itens são incluídos na lista:SELECT GROUP_CONCAT(PetName LIMIT 3)
FROM Pets;
Resultado:
Fluffy,Fetch,Scratch
Qualquer pedido é aplicado antes do
LIMIT
cláusula:SELECT GROUP_CONCAT(PetName ORDER BY PetName DESC LIMIT 3)
FROM Pets;
Resultado:
Wag,Tweet,Scratch
Observe que o
LIMIT
A cláusula é suportada apenas no MariaDB 10.3.3. O DISTINCT
Cláusula
Podemos usar o
DISTINCT
cláusula para retornar valores exclusivos. Em outras palavras, se houver valores duplicados, apenas uma ocorrência será retornada:SELECT GROUP_CONCAT(DISTINCT PetName ORDER BY PetName ASC)
FROM Pets;
Resultado:
Bark,Fetch,Fluffy,Meow,Scratch,Tweet,Wag
Neste caso,
Fluffy
só aparece uma vez. Quando o executamos sem o DISTINCT
cláusula, Fluffy
aparece duas vezes. Mudando o separador
Por padrão, a lista usa a vírgula como delimitador. Mas podemos mudar isso se quisermos:
SELECT GROUP_CONCAT(PetName SEPARATOR '-')
FROM Pets;
Resultado:
Fluffy-Fetch-Scratch-Wag-Tweet-Fluffy-Bark-Meow
Podemos até usar uma string vazia para remover todos os separadores (para que os valores sejam concatenados):
SELECT GROUP_CONCAT(PetName SEPARATOR '')
FROM Pets;
E obtemos o seguinte resultado:
FluffyFetchScratchWagTweetFluffyBarkMeow
Resultados da consulta agrupada
Podemos incluir
GROUP_CONCAT()
em uma consulta com um GROUP BY
cláusula para obter um 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 | +-----------+--------------------------------------------+
No meu banco de dados, os nomes reais dos tipos de animais de estimação estão em outra tabela chamada
PetTypes
. Portanto, poderíamos executar um INNER JOIN
nos PetTypes
table para obter os nomes reais dos tipos de animais de estimação: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 | +---------+------------------------------------------------+
Limitações de comprimento
O comprimento máximo retornado em bytes é determinado pelo
group_concat_max_len
variável de sistema do servidor, cujo padrão é 1M (no MariaDB 10.2.4 e superior) ou 1K (no MariaDB 10.2.3 e inferior). Se group_concat_max_len
é 512
ou inferior, o tipo de retorno é VARBINARY
ou VARCHAR
; caso contrário, o tipo de retorno é BLOB
ou TEXT
. A escolha entre tipos binários ou não binários depende da entrada. Você pode verificar o valor atual assim:
SHOW VARIABLES LIKE '%group_concat%';
A sintaxe para alterar esse valor é a seguinte:
SET [GLOBAL | SESSION] group_concat_max_len = val;
Onde
val
é um inteiro sem sinal.