In MySQL, puoi restituire i risultati della query come un elenco separato da virgole utilizzando GROUP_CONCAT()
funzione.
Il GROUP_CONCAT()
è stata creata appositamente allo scopo di concatenare il set di risultati di una query in un elenco separato da una virgola o da un delimitatore a tua scelta.
Questo articolo fornisce esempi di come funziona.
I dati
Per prima cosa, utilizziamo i seguenti dati nei nostri primi esempi:
USE Solutions; SELECT TaskName FROM Tasks;
Risultato:
+-------------------+ | TaskName | +-------------------+ | Do garden | | Feed cats | | Paint roof | | Take dog for walk | | Relax | | Feed cats | +-------------------+
Esempio di base
Ecco un esempio di base per dimostrare il GROUP_CONCAT()
funzione:
SELECT GROUP_CONCAT(TaskName) FROM Tasks;
Risultato:
+------------------------------------------------------------------+ | GROUP_CONCAT(TaskName) | +------------------------------------------------------------------+ | Do garden,Feed cats,Paint roof,Take dog for walk,Relax,Feed cats | +------------------------------------------------------------------+
Come puoi vedere, ogni riga del set di risultati è stata concatenata in una singola riga. Per impostazione predefinita, l'elenco è separato da una virgola.
Nota che ci sono restrizioni sulla lunghezza di questo elenco. Maggiori informazioni su questo più avanti nell'articolo.
Esempio – DISTINTO
Puoi utilizzare DISTINCT
per rimuovere i duplicati (in modo che i record duplicati diventino un record).
Esempio:
SELECT GROUP_CONCAT(DISTINCT TaskName) FROM Tasks;
Risultato:
+--------------------------------------------------------+ | GROUP_CONCAT(DISTINCT TaskName) | +--------------------------------------------------------+ | Do garden,Feed cats,Paint roof,Relax,Take dog for walk | +--------------------------------------------------------+
Quindi, in questo caso, "Dai da mangiare ai gatti" viene elencato solo una volta, mentre nell'esempio precedente era elencato due volte.
Esempio – ORDINA PER
Puoi utilizzare ORDER BY
per ordinare i risultati in base a una determinata colonna.
Esempio:
SELECT GROUP_CONCAT(DISTINCT TaskName ORDER BY TaskName DESC) FROM Tasks;
Risultato:
+--------------------------------------------------------+ | GROUP_CONCAT(DISTINCT TaskName ORDER BY TaskName DESC) | +--------------------------------------------------------+ | Take dog for walk,Relax,Paint roof,Feed cats,Do garden | +--------------------------------------------------------+
Quindi in questo caso uso DESC
per specificare che dovrebbe essere in ordine decrescente. Il valore alternativo (e predefinito) è ASC
per ascendente.
Esempio:specifica un delimitatore
Per impostazione predefinita, l'elenco è un elenco separato da virgole. Tuttavia, puoi specificare un delimitatore a tua scelta, se necessario.
Per fare ciò, usa SEPARATOR
seguito dal valore letterale della stringa che deve essere inserito tra i valori del gruppo.
Esempio:
SELECT GROUP_CONCAT(DISTINCT TaskName SEPARATOR ' + ') FROM Tasks;
Risultato:
+----------------------------------------------------------------+ | GROUP_CONCAT(DISTINCT TaskName SEPARATOR ' + ') | +----------------------------------------------------------------+ | Do garden + Feed cats + Paint roof + Relax + Take dog for walk | +----------------------------------------------------------------+
Esempio:combinazione di colonne
Puoi anche concatenare colonne e fornire il proprio separatore fornendo un valore letterale stringa.
Esempio:
SELECT GROUP_CONCAT(TaskId, ') ', TaskName SEPARATOR ' ') FROM Tasks;
Risultato:
+------------------------------------------------------------------------------------+ | GROUP_CONCAT(TaskId, ') ', TaskName SEPARATOR ' ') | +------------------------------------------------------------------------------------+ | 1) Do garden 2) Feed cats 3) Paint roof 4) Take dog for walk 5) Relax 6) Feed cats | +------------------------------------------------------------------------------------+
In questo esempio restituiamo entrambi TaskId
colonna e il TaskName
colonna, separata da una parentesi chiusa e da uno spazio. Usiamo anche il SEPARATOR
argomento per specificare che il delimitatore da utilizzare tra ciascuna riga (concatenata) deve essere uno spazio (invece della virgola predefinita).
Risultati raggruppati
Il GROUP_CONCAT()
può essere utile nelle occasioni in cui desideri fornire un elenco di risultati, raggruppati per un'altra colonna.
Ad esempio, potresti volere un elenco di artisti, con ogni artista seguito da un elenco di album che hanno pubblicato.
Per dimostrarlo, supponiamo di avere un database con due tabelle; Artists
e Albums
. C'è una relazione uno a molti tra queste tabelle. Per ogni artista potrebbero esserci molti album.
Quindi una query normale che unisce entrambe le tabelle potrebbe assomigliare a questa:
USE Music; SELECT ar.ArtistName, al.AlbumName FROM Artists ar INNER JOIN Albums al ON ar.ArtistId = al.ArtistId;
Risultato:
+------------------------+--------------------------+ | 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 | +------------------------+--------------------------+
Come puoi vedere, quando utilizzi questo formato, se un artista ha più di un album, quell'artista viene elencato più volte, una per ogni album.
Potremmo modificare questa query in modo che ogni artista sia elencato solo una volta. Se un artista ha più di un album, tutti gli album vengono visualizzati in un unico campo all'interno di un elenco separato da virgole. Possiamo farlo grazie a GROUP_CONCAT()
funzione.
Esempio:
USE Music; SELECT ar.ArtistName, GROUP_CONCAT(al.AlbumName) FROM Artists ar INNER JOIN Albums al ON ar.ArtistId = al.ArtistId GROUP BY ArtistName;
Risultato:
+------------------------+----------------------------------------------------------------------------+ | 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 | +------------------------+----------------------------------------------------------------------------+
Attenzione alla lunghezza!
Una cosa importante di cui devi essere consapevole quando usi GROUP_CONCAT()
è che il risultato viene troncato alla lunghezza massima fornita da group_concat_max_len
variabile di sistema, che ha un valore predefinito di 1024
.
Il valore di questa variabile può essere impostato su un valore più alto, utilizzando la seguente sintassi:
SET [GLOBAL | SESSION] group_concat_max_len = val;
Dove val
è un numero intero senza segno.
Tuttavia, si noti che la lunghezza massima effettiva del valore restituito è essa stessa vincolata dal valore di max_allowed_packet
.