I MySQL kan du returnera dina frågeresultat som en kommaseparerad lista genom att använda GROUP_CONCAT()
funktion.
GROUP_CONCAT()
funktionen byggdes specifikt för syftet att sammanfoga en frågeresultatuppsättning till en lista avgränsad med antingen kommatecken eller valfri avgränsare.
Den här artikeln ger exempel på hur det hela fungerar.
Datan
Låt oss först använda följande data i våra första exempel:
USE Solutions; SELECT TaskName FROM Tasks;
Resultat:
+-------------------+ | TaskName | +-------------------+ | Do garden | | Feed cats | | Paint roof | | Take dog for walk | | Relax | | Feed cats | +-------------------+
Grundläggande exempel
Här är ett grundläggande exempel för att demonstrera GROUP_CONCAT()
funktion:
SELECT GROUP_CONCAT(TaskName) FROM Tasks;
Resultat:
+------------------------------------------------------------------+ | GROUP_CONCAT(TaskName) | +------------------------------------------------------------------+ | Do garden,Feed cats,Paint roof,Take dog for walk,Relax,Feed cats | +------------------------------------------------------------------+
Som du kan se har varje rad från resultatuppsättningen sammanfogats till en enda rad. Som standard är listan avgränsad med ett kommatecken.
Observera att det finns begränsningar för hur lång den här listan kan vara. Mer om detta senare i artikeln.
Exempel – DISTINCT
Du kan använda DISTINCT
för att ta bort dubbletter (så att dubbletter av poster blir en post).
Exempel:
SELECT GROUP_CONCAT(DISTINCT TaskName) FROM Tasks;
Resultat:
+--------------------------------------------------------+ | GROUP_CONCAT(DISTINCT TaskName) | +--------------------------------------------------------+ | Do garden,Feed cats,Paint roof,Relax,Take dog for walk | +--------------------------------------------------------+
Så i det här fallet listas "Feed cats" bara en gång, medan det var listat två gånger i föregående exempel.
Exempel – BESTÄLL AV
Du kan använda ORDER BY
för att sortera resultaten efter en given kolumn.
Exempel:
SELECT GROUP_CONCAT(DISTINCT TaskName ORDER BY TaskName DESC) FROM Tasks;
Resultat:
+--------------------------------------------------------+ | GROUP_CONCAT(DISTINCT TaskName ORDER BY TaskName DESC) | +--------------------------------------------------------+ | Take dog for walk,Relax,Paint roof,Feed cats,Do garden | +--------------------------------------------------------+
Så i det här fallet använder jag DESC
för att ange att det ska vara i fallande ordning. Det alternativa (och standardvärdet) värdet är ASC
för stigande.
Exempel – Ange en avgränsare
Som standard är listan en kommaseparerad lista. Du kan dock ange en valfri avgränsare om det behövs.
För att göra detta, använd SEPARATOR
följt av strängens bokstavliga värde som ska infogas mellan gruppvärden.
Exempel:
SELECT GROUP_CONCAT(DISTINCT TaskName SEPARATOR ' + ') FROM Tasks;
Resultat:
+----------------------------------------------------------------+ | GROUP_CONCAT(DISTINCT TaskName SEPARATOR ' + ') | +----------------------------------------------------------------+ | Do garden + Feed cats + Paint roof + Relax + Take dog for walk | +----------------------------------------------------------------+
Exempel – Kombinera kolumner
Du kan också sammanfoga kolumner och tillhandahålla en egen separator genom att ange ett bokstavligt värde för strängen.
Exempel:
SELECT GROUP_CONCAT(TaskId, ') ', TaskName SEPARATOR ' ') FROM Tasks;
Resultat:
+------------------------------------------------------------------------------------+ | GROUP_CONCAT(TaskId, ') ', TaskName SEPARATOR ' ') | +------------------------------------------------------------------------------------+ | 1) Do garden 2) Feed cats 3) Paint roof 4) Take dog for walk 5) Relax 6) Feed cats | +------------------------------------------------------------------------------------+
I det här exemplet returnerar vi både TaskId
kolumnen och TaskName
kolumn, åtskilda av en avslutande parentes och ett mellanslag. Vi använder också SEPARATOR
argument för att specificera att avgränsaren som ska användas mellan varje (sammanfogad) rad ska vara ett mellanslag (istället för standardkomma).
Grupperade resultat
GROUP_CONCAT()
funktionen kan vara användbar för tillfällen där du vill tillhandahålla en lista med resultat, grupperad efter en annan kolumn.
Du kanske till exempel vill ha en lista över artister, med varje artist följt av en lista över album de har släppt.
För att visa detta, säg att vi har en databas med två tabeller; Artists
och Albums
. Det finns ett ett till många förhållande mellan dessa tabeller. För varje artist kan det finnas många album.
Så en vanlig fråga som förenar båda tabellerna kan se ut ungefär så här:
USE Music; SELECT ar.ArtistName, al.AlbumName FROM Artists ar INNER JOIN Albums al ON ar.ArtistId = al.ArtistId;
Resultat:
+------------------------+--------------------------+ | 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 | +------------------------+--------------------------+
Som du kan se, när du använder det här formatet, om en artist har mer än ett album, listas den artisten flera gånger – en gång för varje album.
Vi skulle kunna ändra den här frågan så att varje artist bara listas en gång. Om en artist har mer än ett album visas alla album i ett enda fält i en kommaseparerad lista. Vi kan göra detta tack vare GROUP_CONCAT()
funktion.
Exempel:
USE Music; SELECT ar.ArtistName, GROUP_CONCAT(al.AlbumName) FROM Artists ar INNER JOIN Albums al ON ar.ArtistId = al.ArtistId GROUP BY ArtistName;
Resultat:
+------------------------+----------------------------------------------------------------------------+ | 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 | +------------------------+----------------------------------------------------------------------------+
Var försiktig med längden!
En viktig sak du måste vara medveten om när du använder GROUP_CONCAT()
är att resultatet är trunkerat till den maximala längden som tillhandahålls av group_concat_max_len
systemvariabel, som har ett standardvärde på 1024
.
Variabelns värde kan ställas in högre genom att använda följande syntax:
SET [GLOBAL | SESSION] group_concat_max_len = val;
Där val
är ett heltal utan tecken.
Observera dock att den effektiva maximala längden för returvärdet i sig är begränsad av värdet på max_allowed_packet
.