V MySQL můžete vrátit výsledky dotazu jako seznam oddělený čárkami pomocí GROUP_CONCAT()
funkce.
GROUP_CONCAT()
funkce byla vytvořena speciálně pro účely zřetězení sady výsledků dotazu do seznamu odděleného buď čárkou, nebo oddělovačem dle vašeho výběru.
Tento článek uvádí příklady, jak to celé funguje.
Data
Nejprve použijeme v několika prvních příkladech následující data:
USE Solutions; SELECT TaskName FROM Tasks;
Výsledek:
+-------------------+ | TaskName | +-------------------+ | Do garden | | Feed cats | | Paint roof | | Take dog for walk | | Relax | | Feed cats | +-------------------+
Základní příklad
Zde je základní příklad demonstrující GROUP_CONCAT()
funkce:
SELECT GROUP_CONCAT(TaskName) FROM Tasks;
Výsledek:
+------------------------------------------------------------------+ | GROUP_CONCAT(TaskName) | +------------------------------------------------------------------+ | Do garden,Feed cats,Paint roof,Take dog for walk,Relax,Feed cats | +------------------------------------------------------------------+
Jak můžete vidět, každý řádek ze sady výsledků byl zřetězen do jednoho řádku. Ve výchozím nastavení je seznam oddělen čárkou.
Upozorňujeme, že existují omezení týkající se délky tohoto seznamu. Více o tom později v článku.
Příklad – DISTINCT
Můžete použít DISTINCT
k odstranění duplikátů (tak, aby se duplicitní záznamy staly jedním záznamem).
Příklad:
SELECT GROUP_CONCAT(DISTINCT TaskName) FROM Tasks;
Výsledek:
+--------------------------------------------------------+ | GROUP_CONCAT(DISTINCT TaskName) | +--------------------------------------------------------+ | Do garden,Feed cats,Paint roof,Relax,Take dog for walk | +--------------------------------------------------------+
V tomto případě je tedy „Nakrmit kočky“ uvedeno pouze jednou, zatímco v předchozím příkladu bylo uvedeno dvakrát.
Příklad – ORDER BY
Můžete použít ORDER BY
seřadit výsledky podle daného sloupce.
Příklad:
SELECT GROUP_CONCAT(DISTINCT TaskName ORDER BY TaskName DESC) FROM Tasks;
Výsledek:
+--------------------------------------------------------+ | GROUP_CONCAT(DISTINCT TaskName ORDER BY TaskName DESC) | +--------------------------------------------------------+ | Take dog for walk,Relax,Paint roof,Feed cats,Do garden | +--------------------------------------------------------+
Takže v tomto případě používám DESC
určit, že by měl být v sestupném pořadí. Alternativní (a výchozí) hodnota je ASC
pro vzestupné.
Příklad – Zadejte oddělovač
Ve výchozím nastavení je seznam seznam oddělený čárkami. V případě potřeby však můžete zadat oddělovač podle svého výběru.
K tomu použijte SEPARATOR
následuje hodnota řetězcového literálu, která by měla být vložena mezi hodnoty skupiny.
Příklad:
SELECT GROUP_CONCAT(DISTINCT TaskName SEPARATOR ' + ') FROM Tasks;
Výsledek:
+----------------------------------------------------------------+ | GROUP_CONCAT(DISTINCT TaskName SEPARATOR ' + ') | +----------------------------------------------------------------+ | Do garden + Feed cats + Paint roof + Relax + Take dog for walk | +----------------------------------------------------------------+
Příklad – Kombinování sloupců
Můžete také zřetězit sloupce a poskytnout jejich vlastní oddělovač zadáním hodnoty řetězcového literálu.
Příklad:
SELECT GROUP_CONCAT(TaskId, ') ', TaskName SEPARATOR ' ') FROM Tasks;
Výsledek:
+------------------------------------------------------------------------------------+ | GROUP_CONCAT(TaskId, ') ', TaskName SEPARATOR ' ') | +------------------------------------------------------------------------------------+ | 1) Do garden 2) Feed cats 3) Paint roof 4) Take dog for walk 5) Relax 6) Feed cats | +------------------------------------------------------------------------------------+
V tomto příkladu vrátíme oba TaskId
a TaskName
sloupec oddělený uzavírací závorkou a mezerou. Používáme také SEPARATOR
argument k určení, že oddělovačem, který se má použít mezi každým (zřetězeným) řádkem, by měla být mezera (místo výchozí čárky).
Skupinové výsledky
GROUP_CONCAT()
funkce může být užitečná v případech, kdy chcete poskytnout seznam výsledků seskupený podle jiného sloupce.
Můžete například chtít seznam umělců, za každým následuje seznam alb, která vydali.
Abychom to demonstrovali, řekněme, že máme databázi se dvěma tabulkami; Artists
a Albums
. Mezi těmito tabulkami existuje vztah jedna k mnoha. Pro každého umělce může existovat mnoho alb.
Takže běžný dotaz spojující obě tabulky může vypadat nějak takto:
USE Music; SELECT ar.ArtistName, al.AlbumName FROM Artists ar INNER JOIN Albums al ON ar.ArtistId = al.ArtistId;
Výsledek:
+------------------------+--------------------------+ | 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 můžete vidět, při použití tohoto formátu, pokud má interpret více než jedno album, je tento interpret uveden vícekrát – pro každé album jednou.
Tento dotaz bychom mohli upravit tak, aby byl každý umělec uveden pouze jednou. Pokud má interpret více než jedno album, všechna alba se zobrazí v jednom poli v seznamu odděleném čárkami. Můžeme to udělat díky GROUP_CONCAT()
funkce.
Příklad:
USE Music; SELECT ar.ArtistName, GROUP_CONCAT(al.AlbumName) FROM Artists ar INNER JOIN Albums al ON ar.ArtistId = al.ArtistId GROUP BY ArtistName;
Výsledek:
+------------------------+----------------------------------------------------------------------------+ | 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 | +------------------------+----------------------------------------------------------------------------+
Pozor na délku!
Při používání GROUP_CONCAT()
si musíte uvědomit jednu důležitou věc je, že výsledek je zkrácen na maximální délku, kterou poskytuje group_concat_max_len
systémová proměnná, která má výchozí hodnotu 1024
.
Hodnotu této proměnné lze nastavit vyšší pomocí následující syntaxe:
SET [GLOBAL | SESSION] group_concat_max_len = val;
Kde val
je celé číslo bez znaménka.
Mějte však na paměti, že efektivní maximální délka vrácené hodnoty je sama o sobě omezena hodnotou max_allowed_packet
.