Sante Caserio
pubblicato più di 2 anni fa

La funzione di aggregazione GROUP_CONCAT()

L’articolo descrive la funzione di aggregazione group_concat() partendo da un rapido excursus teorico alle applicazioni pratiche

Dalla versione 4.1 MySQL fornisce la funzione GROUP_CONCAT(). Questa è una funzione di aggregazione che consente concatenare in un’unica stringa un gruppo di valori che normalmente si trovano su record differenti. Un esempio per chiarire:

1SELECT l.titolo AS titolo, GROUP_CONCAT(a.nome) AS autori
2FROM libro l
3LEFT JOIN libro_autore la ON l.id=la.id_libro
4LEFT JOIN autore a ON la.id_autore=a.id
5GROUP BY l.id

E’ facile intuire che la tabella libro_autore rappresenta un’associazione “molti a molti” tra i libri e gli autori. La qui presente doppia JOIN restituisce, per ogni libro, tutti i suoi autori. Grazie alla funzione GROUP_CONCAT() però ogni associazione libro-autore non è un singolo record. Vi è infatti, un unico record per ogni libro e tutti gli autori sono elencati nel valore “autori”, separati da virgole. Un esempio di possibili risultati è il seguente:

titolo: The C Programming Language autori: B. W. Kernighan,Dennis Ritchie titolo: La gioia armata autori: A. M. Bonanno

Vi sono poi alcuni parametri che rendono il suo utilizzo più flessibile e più comodo all’interno di una applicazione. Ecco la sintassi completa:

1GROUP_CONCAT([DISTINCT] espressione [, espressione ...]
2[ORDER BY {unsigned_integer | nome_colonna | espressione}
3[ASC | DESC] [, nome_colonna ...]]
4[SEPARATOR stringa])

Nella maggior parte dei casi, useremo GROUP_CONCAT() per ottenere la lista dei valori presenti in un campo A che sono associati a determinati valori presenti in un campo B. Nell’esempio, otteniamo una lista di autori che sono associati ad ogni singolo titolo. Per fare questo, naturalmente, si usa la clausola GROUP BY. Si può non usarla se si desidera concatenare in un’unica stringa tutti i valori esistenti in una tabella, ma questo è un caso piuttosto raro; inoltre non è consigliabile su tabelle di dimensioni medio-grandi perchè la query risulterebbe piuttosto impegnativa per il server. Infine, teniamo presente che in un database relazionale è piuttosto frequente che le query contenenti GROUP_CONCAT() coinvolgano più di una tabella (JOIN).

Il separatore

Poiché lo scopo principale di GROUP_CONCAT() è fornire un elenco di valori già pronti per essere visualizzati, è utile impostare il carattere o i caratteri che devono separare questi valori. Il separatore predefinito è la virgola, senza alcuno spazio prima o dopo. Questo va bene nel caso si voglia ottenere una stringa che PHP “esploderà” in un array tramite la funzione explode() (o qualche altro linguaggio la esploderà con qualche altra funzione). Anche questo però è possibile solo se i valori da concatenare non contengono virgole, altrimenti bisognerà utilizzare un altro carattere. Il seguente esempio mostra come concatenare valori separandoli con una virgola e uno spazio, in modo che possano avere un aspetto gradevole e comprensibile alle persone che li usano senza modifiche da parte di PHP o altri linguaggi:

1SELECT l.titolo AS titolo, GROUP_CONCAT(a.nome SEPARATOR , ) AS autori
2FROM libro l
3LEFT JOIN libro_autore la ON l.id=la.id_libro
4LEFT JOIN autore a ON la.id_autore=a.id
5GROUP BY l.id

L’ordinamento

L’ordine dei valori restituiti dalla clausola GROUP_CONCAT() possono essere modificato nella query, per fare ciò si utilizza la clausola ORDER BY di GROUP_CONCAT(). Il suo utilizzo è sintatticamente identico a quello dell’ORDER BY delle SELECT. Infatti permette di specificare il nome di un campo, il numero della sua posizione, oppure una qualsiasi espressione SQL. Si può anche utilizzare le parole chiave ASC (ascending; è l’ordinamento predefinito) e DESC (descending). La clausola ORDER BY di GROUP_CONCAT() però non va confusa con l’ORDER BY che accompagna le SELECT. Bisogna infatti ricordare che la prima influenza l’ordinamento dei valori concatenati da GROUP_CONCAT() (esempio: “autore1, autore2, autore3”), mentre la seconda influenza l’ordine dei record. Bisogna ricordare che, poiché spesso saremo in presenza di una query con GROUP BY, per default è questa clausola a determinare l’ordinamento dei record. Essa ammette l’uso delle parole chiave ASC e DESC:

1SELECT ... GROUP BY autore DESC

Esempio di uso di ORDER BY:

1SELECT ... GROUP BY autore ORDER BY id

Se infine si desidera che i record vengano restituiti in ordine sparso (ma questo non migliorerà le prestazioni della query):

1SELECT ... GROUP BY autore ORDER BY NULL

Un esempio di query completa:

1SELECT l.titolo AS titolo, 
2GROUP_CONCAT(a.nome ORDER BY a.nome DESC SEPARATOR ', ') 
3AS autori
4FROM libro l
5LEFT JOIN libro_autore la ON l.id=la.id_libro
6LEFT JOIN autore a ON la.id_autore=a.id
7GROUP BY l.id ORDER BY NULL

Distinct

Se esistono valori duplicati, per default GROUP_CONCAT() li restituirà tutti. Nella “vita reale” in genere questo non può avvenire; se però la possibilità esiste, potremmo voler eliminare tali valori:

1SELECT l.titolo AS titolo, GROUP_CONCAT(DISTINCT a.nome) AS autori
2FROM libro l
3LEFT JOIN libro_autore la ON l.id=la.id_libro
4LEFT JOIN autore a ON la.id_autore=a.id
5GROUP BY l.id

Prestazioni

Spesso l’uso di GROUP_CONCAT() può ridurre le comunicazioni tra il client e il server MySQL, che generalmente costituiscono uno dei colli di bottiglia. Inoltre la funzione in sè sembra essere abbastanza veloce.

Limiti

Vi è un limite al numero di record che possono essere concatenati. Esso è rappresentato dalla variabile group_concat_max_len, il cui valore predefinito è 1024. La variabile è modificabile a run time.

Esempio:

1SET GLOBAL group_concat_max_len=4096

Se poi desideriamo modificare in modo permanente tale limite, basta agire sul file my.cnf.

Condividi su:

Esprimi un voto:

  • Current rating: 0.0/5
  • 1
  • 2
  • 3
  • 4
  • 5

Argomenti chiave:

Ultimi commenti Ultimi commenti

Esegui il Login oppure registrati per scrivere un commento.
Cerca nel sito...
Ultime recipes

Un utilissimo tool di shell che effettua un dettagliato e comodo report su MySQL MySQL Report un tool di shell per tenere tutto sotto controllo

Un utilissimo tool di shell che effettua un dettagliato e comodo report su MySQL


Vai alla recipe

Un utilissimo tool per sniffare il traffico Client/Server TCP/IP di MySQL MySQLSniffer sniffare il traffico TCP di MySQL

Un utilissimo tool per sniffare il traffico Client/Server TCP/IP di MySQL


Vai alla recipe

Verificare l'integrità, riparare gestire chiavi e memoria di tabelle MyISAM attraverso myisamchk riparare file MyISAM

Verificare l'integrità, riparare gestire chiavi e memoria di tabelle MyISAM attraverso il file myisamchk


Vai alla recipe

Un tool per comprimere le tabelle MyISAM fino a oltre il 50% myisampack comprimere file MyISAM

Un tool per comprimere le tabelle MyISAM fino a oltre il 50%


Vai alla recipe

mysqlshow le info di base sui database, tabelle e colonne senza utilizzare alcun mysqlshow visualizzare le informazioni sul database MySQL

mysqlshow le info di base sui database, tabelle e colonne senza utilizzare alcun client


Vai alla recipe

Utilizzando UNION / UNION ALL su campi int unsigned zerofill,
ho notato che MysqlUNION / UNION ALL su campi int unsigned zerofill. di DebUsr
Vai al tip

Utilizzo di funzioni come alias di campo tramite l'impiego di prepared statementReport con alias di campo dinamici di john_revelator
Vai al tip

Può capitare che sia necessario eseguire un dump di database in formato Comma SeparatedEsecuzione dump in formato CSV (tabelle in engine MyIsam esportate in formato CSV) di ghigomatto
Vai al tip

E' possibile eseguire le query SQL contenute in un file di testo. Questo è utileEseguire le query da un file di testo di Sante Caserio
Vai al tip

Se vogliamo fare il backup di tutti i database con mysqldump, e ne abbiamo parecchiFare il backup di tutti i database di Sante Caserio
Vai al tip

Salve, dopo tante storie ho studiato il php e mysql .. . che in questo forum parlavo php e campo mysql timestamp di gigi Vai al topic

ciao a tutti ho creato un forum su aruba ma non so come farlo visualizzare nel mio aruba di albertodiprima Vai al topic

Salve a tutti gente, questo è il mio primo post su questo forum e questo a causa Problema Gravissimo con AutoIncrement di stefanoadsl Vai al topic

Salve! Mi presento, mi chiamo Adriano e sono uno studente di ingegneria informatica Problema Trigger di Xanakro Vai al topic

Ciao a tutti!
Volevo chiedere una informazione.
Ho una query che lanciata la prima Query Eseguita più volte di OltreLeStelle Vai al topic