W MySQL możesz zwrócić wyniki zapytania jako listę oddzieloną przecinkami, używając GROUP_CONCAT()
funkcja.
GROUP_CONCAT()
funkcja została zbudowana specjalnie w celu łączenia zestawu wyników zapytania w listę oddzieloną przecinkiem lub wybranym przez Ciebie ogranicznikiem.
Ten artykuł zawiera przykłady, jak to wszystko działa.
Dane
Najpierw użyjmy następujących danych w naszych pierwszych kilku przykładach:
USE Solutions; SELECT TaskName FROM Tasks;
Wynik:
+-------------------+ | TaskName | +-------------------+ | Do garden | | Feed cats | | Paint roof | | Take dog for walk | | Relax | | Feed cats | +-------------------+
Przykład podstawowy
Oto podstawowy przykład demonstrujący GROUP_CONCAT()
funkcja:
SELECT GROUP_CONCAT(TaskName) FROM Tasks;
Wynik:
+------------------------------------------------------------------+ | GROUP_CONCAT(TaskName) | +------------------------------------------------------------------+ | Do garden,Feed cats,Paint roof,Take dog for walk,Relax,Feed cats | +------------------------------------------------------------------+
Jak widać, każdy wiersz z zestawu wyników został połączony w jeden wiersz. Domyślnie lista jest oddzielona przecinkiem.
Pamiętaj, że istnieją ograniczenia dotyczące długości tej listy. Więcej na ten temat w dalszej części artykułu.
Przykład – RÓŻNE
Możesz użyć DISTINCT
aby usunąć duplikaty (tak, aby zduplikowane rekordy stały się jednym rekordem).
Przykład:
SELECT GROUP_CONCAT(DISTINCT TaskName) FROM Tasks;
Wynik:
+--------------------------------------------------------+ | GROUP_CONCAT(DISTINCT TaskName) | +--------------------------------------------------------+ | Do garden,Feed cats,Paint roof,Relax,Take dog for walk | +--------------------------------------------------------+
Tak więc w tym przypadku „Karm koty” jest wymieniony tylko raz, podczas gdy w poprzednim przykładzie był wymieniony dwukrotnie.
Przykład – ZAMÓW PRZEZ
Możesz użyć ORDER BY
aby uporządkować wyniki według danej kolumny.
Przykład:
SELECT GROUP_CONCAT(DISTINCT TaskName ORDER BY TaskName DESC) FROM Tasks;
Wynik:
+--------------------------------------------------------+ | GROUP_CONCAT(DISTINCT TaskName ORDER BY TaskName DESC) | +--------------------------------------------------------+ | Take dog for walk,Relax,Paint roof,Feed cats,Do garden | +--------------------------------------------------------+
Więc w tym przypadku używam DESC
aby określić, że powinien być w porządku malejącym. Alternatywną (i domyślną) wartością jest ASC
do wznoszenia.
Przykład — określ ogranicznik
Domyślnie lista jest listą oddzieloną przecinkami. W razie potrzeby możesz jednak określić wybrany ogranicznik.
Aby to zrobić, użyj SEPARATOR
po którym następuje literał ciągu znaków, który należy wstawić między wartościami grup.
Przykład:
SELECT GROUP_CONCAT(DISTINCT TaskName SEPARATOR ' + ') FROM Tasks;
Wynik:
+----------------------------------------------------------------+ | GROUP_CONCAT(DISTINCT TaskName SEPARATOR ' + ') | +----------------------------------------------------------------+ | Do garden + Feed cats + Paint roof + Relax + Take dog for walk | +----------------------------------------------------------------+
Przykład – łączenie kolumn
Możesz także łączyć kolumny i udostępniać ich własny separator, podając wartość literału ciągu.
Przykład:
SELECT GROUP_CONCAT(TaskId, ') ', TaskName SEPARATOR ' ') FROM Tasks;
Wynik:
+------------------------------------------------------------------------------------+ | GROUP_CONCAT(TaskId, ') ', TaskName SEPARATOR ' ') | +------------------------------------------------------------------------------------+ | 1) Do garden 2) Feed cats 3) Paint roof 4) Take dog for walk 5) Relax 6) Feed cats | +------------------------------------------------------------------------------------+
W tym przykładzie zwracamy oba TaskId
kolumna i TaskName
kolumna, oddzielona nawiasami zamykającymi i spacją. Używamy również SEPARATOR
argument określający, że separatorem, który ma być używany między każdym (połączonym) wierszem, powinien być spacja (zamiast domyślnego przecinka).
Zgrupowane wyniki
GROUP_CONCAT()
funkcja może być przydatna w sytuacjach, w których chcesz podać listę wyników pogrupowanych według innej kolumny.
Na przykład możesz potrzebować listy wykonawców, z każdym wykonawcą, po którym następuje lista albumów, które wydali.
Aby to zademonstrować, powiedzmy, że mamy bazę danych z dwiema tabelami; Artists
i Albums
. Między tymi tabelami istnieje relacja jeden do wielu. Dla każdego wykonawcy może być wiele albumów.
Tak więc zwykłe zapytanie łączące obie tabele może wyglądać mniej więcej tak:
USE Music; SELECT ar.ArtistName, al.AlbumName FROM Artists ar INNER JOIN Albums al ON ar.ArtistId = al.ArtistId;
Wynik:
+------------------------+--------------------------+ | ArtistName | AlbumName | +------------------------+--------------------------+ | Iron Maiden | Powerslave | | AC/DC | Powerage | | Jim Reeves | Singing Down the Lane | | Devin Townsend | Ziltoid the Omniscient | | Devin Townsend | Casualties of Cool | | Devin Townsend | Epicloud | | Iron Maiden | Somewhere in Time | | Iron Maiden | Piece of Mind | | Iron Maiden | Killers | | Iron Maiden | No Prayer for the Dying | | The Script | No Sound Without Silence | | Buddy Rich | Big Swing Face | | Michael Learns to Rock | Blue Night | | Michael Learns to Rock | Eternity | | Michael Learns to Rock | Scandinavia | | Tom Jones | Long Lost Suitcase | | Tom Jones | Praise and Blame | | Tom Jones | Along Came Jones | | Allan Holdsworth | All Night Wrong | | Allan Holdsworth | The Sixteen Men of Tain | +------------------------+--------------------------+
Jak widać, podczas korzystania z tego formatu, jeśli wykonawca ma więcej niż jeden album, jest on wymieniany wielokrotnie – raz dla każdego albumu.
Moglibyśmy zmodyfikować to zapytanie, tak aby każdy wykonawca był wymieniony tylko raz. Jeśli wykonawca ma więcej niż jeden album, wszystkie albumy są wyświetlane w jednym polu na liście oddzielonej przecinkami. Możemy to zrobić dzięki GROUP_CONCAT()
funkcja.
Przykład:
USE Music; SELECT ar.ArtistName, GROUP_CONCAT(al.AlbumName) FROM Artists ar INNER JOIN Albums al ON ar.ArtistId = al.ArtistId GROUP BY ArtistName;
Wynik:
+------------------------+----------------------------------------------------------------------------+ | ArtistName | GROUP_CONCAT(al.AlbumName) | +------------------------+----------------------------------------------------------------------------+ | AC/DC | Powerage | | Allan Holdsworth | All Night Wrong,The Sixteen Men of Tain | | Buddy Rich | Big Swing Face | | Devin Townsend | Epicloud,Ziltoid the Omniscient,Casualties of Cool | | Iron Maiden | Somewhere in Time,Piece of Mind,Powerslave,Killers,No Prayer for the Dying | | Jim Reeves | Singing Down the Lane | | Michael Learns to Rock | Eternity,Scandinavia,Blue Night | | The Script | No Sound Without Silence | | Tom Jones | Long Lost Suitcase,Praise and Blame,Along Came Jones | +------------------------+----------------------------------------------------------------------------+
Uważaj na długość!
Jedna ważna rzecz, o której musisz pamiętać podczas korzystania z GROUP_CONCAT()
jest to, że wynik jest obcinany do maksymalnej długości podanej przez group_concat_max_len
zmienna systemowa, która ma domyślną wartość 1024
.
Wartość tej zmiennej można ustawić na wyższą, używając następującej składni:
SET [GLOBAL | SESSION] group_concat_max_len = val;
Gdzie val
jest liczbą całkowitą bez znaku.
Należy jednak pamiętać, że efektywna maksymalna długość zwracanej wartości jest sama ograniczona przez wartość max_allowed_packet
.