MySQL har en GROUP_CONCAT()
funktion, der gør det muligt for os at returnere kolonner fra en forespørgsel som en afgrænset liste.
Det returnerer et strengresultat med den sammenkædede ikke-NULL
værdier fra en gruppe.
Syntaks
Syntaksen ser sådan ud:
GROUP_CONCAT([DISTINCT] expr [,expr ...]
[ORDER BY {unsigned_integer | col_name | expr}
[ASC | DESC] [,col_name ...]]
[SEPARATOR str_val])
Eksempel
Antag, at vi kører følgende forespørgsel:
SELECT PetName
FROM Pets;
Og vi får følgende resultat:
+---------+ | PetName | +---------+ | Fluffy | | Fetch | | Scratch | | Wag | | Tweet | | Fluffy | | Bark | | Meow | +---------+ 8 rows in set (0.00 sec)
Vi kan bruge GROUP_CONCAT()
for at returnere alle disse rækker som en afgrænset liste.
For at gøre dette skal vi videregive PetName
kolonne som et argument til GROUP_CONCAT()
funktion:
SELECT GROUP_CONCAT(PetName)
FROM Pets;
Resultat:
+-------------------------------------------------+ | GROUP_CONCAT(PetName) | +-------------------------------------------------+ | Fluffy,Fetch,Scratch,Wag,Tweet,Fluffy,Bark,Meow | +-------------------------------------------------+ 1 row in set (0.01 sec)
Bestilling
Vi kan bruge ORDER BY
klausul for at bestille output af denne funktion:
SELECT GROUP_CONCAT(PetName ORDER BY PetName ASC)
FROM Pets;
Resultat:
Bark,Fetch,Fluffy,Fluffy,Meow,Scratch,Tweet,Wag
Bemærk, at dette kun sorterer output fra GROUP_CONCAT()
funktion – den er fuldstændig uafhængig af enhver bestilling, der anvendes på SELECT
selve erklæringen.
DISTINCT
Klausul
Vi kan bruge DISTINCT
klausul for at returnere unikke værdier. Med andre ord, hvis der er duplikerede værdier, returneres kun én forekomst:
SELECT GROUP_CONCAT(DISTINCT PetName ORDER BY PetName ASC)
FROM Pets;
Resultat:
Bark,Fetch,Fluffy,Meow,Scratch,Tweet,Wag
I dette tilfælde Fluffy
vises kun én gang. Når vi kører det uden DISTINCT
klausul, Fluffy
vises to gange.
Ændring af separatoren
Som standard bruger listen kommaet som skilletegn. Men vi kan ændre dette, hvis vi vil:
SELECT GROUP_CONCAT(PetName SEPARATOR '-')
FROM Pets;
Resultat:
Fluffy-Fetch-Scratch-Wag-Tweet-Fluffy-Bark-Meow
Vi kan endda bruge en tom streng til at fjerne alle separatorer (så værdierne er sammenkædet):
SELECT GROUP_CONCAT(PetName SEPARATOR '')
FROM Pets;
Og vi får følgende resultat:
FluffyFetchScratchWagTweetFluffyBarkMeow
Resultater af grupperet forespørgsel
Vi kan inkludere GROUP_CONCAT()
i en forespørgsel med en GROUP BY
klausul for at opnå et resultat som dette:
SELECT
PetTypeId,
GROUP_CONCAT(PetName ORDER BY PetName ASC)
FROM Pets
GROUP BY PetTypeId
ORDER BY PetTypeId;
Resultat:
+-----------+--------------------------------------------+ | PetTypeId | GROUP_CONCAT(PetName ORDER BY PetName ASC) | +-----------+--------------------------------------------+ | 1 | Tweet | | 2 | Fluffy,Meow,Scratch | | 3 | Bark,Fetch,Fluffy,Wag | +-----------+--------------------------------------------+
I min database er de faktiske kæledyrstypenavne i en anden tabel kaldet PetTypes
. Vi kunne derfor køre en INNER JOIN
på PetTypes
tabel for at få de faktiske kæledyrstypenavne:
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;
Resultat:
+---------+------------------------------------------------+ | PetType | GROUP_CONCAT(p.PetName ORDER BY p.PetName ASC) | +---------+------------------------------------------------+ | Bird | Tweet | | Cat | Fluffy,Meow,Scratch | | Dog | Bark,Fetch,Fluffy,Wag | +---------+------------------------------------------------+
Længdebegrænsninger
GROUP_CONCAT()
's output er trunkeret til den maksimale længde, der er givet af group_concat_max_len
systemvariabel, som har en standardværdi på 1024
. Værdien kan indstilles højere, selvom den effektive maksimale længde af returværdien er begrænset af værdien max_allowed_packet
.
Du kan kontrollere den aktuelle værdi på denne måde:
SHOW VARIABLES LIKE '%group_concat%';
Syntaksen for at ændre denne værdi er som følger:
SET [GLOBAL | SESSION] group_concat_max_len = val;
Hvor val
er et heltal uden fortegn.