MySQL ma GROUP_CONCAT()
funkcja, która umożliwia nam zwracanie kolumn z zapytania w postaci rozdzielanej listy.
Zwraca wynik w postaci ciągu z połączonymi wartościami innymi niż NULL
wartości z grupy.
Składnia
Składnia wygląda tak:
GROUP_CONCAT([DISTINCT] expr [,expr ...]
[ORDER BY {unsigned_integer | col_name | expr}
[ASC | DESC] [,col_name ...]]
[SEPARATOR str_val])
Przykład
Załóżmy, że uruchamiamy następujące zapytanie:
SELECT PetName
FROM Pets;
I otrzymujemy następujący wynik:
+---------+ | PetName | +---------+ | Fluffy | | Fetch | | Scratch | | Wag | | Tweet | | Fluffy | | Bark | | Meow | +---------+ 8 rows in set (0.00 sec)
Możemy użyć GROUP_CONCAT()
aby zwrócić wszystkie te wiersze jako listę rozdzielaną.
Aby to zrobić, musimy przekazać PetName
kolumna jako argument do GROUP_CONCAT()
funkcja:
SELECT GROUP_CONCAT(PetName)
FROM Pets;
Wynik:
+-------------------------------------------------+ | GROUP_CONCAT(PetName) | +-------------------------------------------------+ | Fluffy,Fetch,Scratch,Wag,Tweet,Fluffy,Bark,Meow | +-------------------------------------------------+ 1 row in set (0.01 sec)
Zamawianie
Możemy użyć ORDER BY
klauzula porządkująca wyjście tej funkcji:
SELECT GROUP_CONCAT(PetName ORDER BY PetName ASC)
FROM Pets;
Wynik:
Bark,Fetch,Fluffy,Fluffy,Meow,Scratch,Tweet,Wag
Zauważ, że to sortuje tylko dane wyjściowe GROUP_CONCAT()
funkcja – jest całkowicie niezależna od dowolnej kolejności zastosowanej do SELECT
samo oświadczenie.
DISTINCT
Klauzula
Możemy użyć DISTINCT
klauzula zwracająca unikalne wartości. Innymi słowy, jeśli istnieją zduplikowane wartości, zwracane jest tylko jedno wystąpienie:
SELECT GROUP_CONCAT(DISTINCT PetName ORDER BY PetName ASC)
FROM Pets;
Wynik:
Bark,Fetch,Fluffy,Meow,Scratch,Tweet,Wag
W tym przypadku Fluffy
pojawia się tylko raz. Kiedy uruchamiamy go bez DISTINCT
klauzula, Fluffy
pojawia się dwukrotnie.
Zmiana separatora
Domyślnie lista używa przecinka jako ogranicznika. Ale możemy to zmienić, jeśli chcemy:
SELECT GROUP_CONCAT(PetName SEPARATOR '-')
FROM Pets;
Wynik:
Fluffy-Fetch-Scratch-Wag-Tweet-Fluffy-Bark-Meow
Możemy nawet użyć pustego ciągu, aby usunąć wszystkie separatory (aby wartości były połączone):
SELECT GROUP_CONCAT(PetName SEPARATOR '')
FROM Pets;
I otrzymujemy następujący wynik:
FluffyFetchScratchWagTweetFluffyBarkMeow
Zgrupowane wyniki zapytań
Możemy dołączyć GROUP_CONCAT()
w zapytaniu z GROUP BY
klauzula, aby osiągnąć taki wynik:
SELECT
PetTypeId,
GROUP_CONCAT(PetName ORDER BY PetName ASC)
FROM Pets
GROUP BY PetTypeId
ORDER BY PetTypeId;
Wynik:
+-----------+--------------------------------------------+ | PetTypeId | GROUP_CONCAT(PetName ORDER BY PetName ASC) | +-----------+--------------------------------------------+ | 1 | Tweet | | 2 | Fluffy,Meow,Scratch | | 3 | Bark,Fetch,Fluffy,Wag | +-----------+--------------------------------------------+
W mojej bazie danych rzeczywiste nazwy typów zwierząt znajdują się w innej tabeli o nazwie PetTypes
. Mogliśmy zatem uruchomić INNER JOIN
w PetTypes
tabela, aby uzyskać rzeczywiste nazwy typów zwierząt:
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;
Wynik:
+---------+------------------------------------------------+ | PetType | GROUP_CONCAT(p.PetName ORDER BY p.PetName ASC) | +---------+------------------------------------------------+ | Bird | Tweet | | Cat | Fluffy,Meow,Scratch | | Dog | Bark,Fetch,Fluffy,Wag | +---------+------------------------------------------------+
Ograniczenia długości
GROUP_CONCAT()
Dane wyjściowe są obcinane do maksymalnej długości podanej przez group_concat_max_len
zmienna systemowa, która ma domyślną wartość 1024
. Wartość można ustawić wyżej, chociaż efektywna maksymalna długość zwracanej wartości jest ograniczona wartością max_allowed_packet
.
Możesz sprawdzić aktualną wartość w ten sposób:
SHOW VARIABLES LIKE '%group_concat%';
Składnia zmiany tej wartości wygląda następująco:
SET [GLOBAL | SESSION] group_concat_max_len = val;
Gdzie val
jest liczbą całkowitą bez znaku.