MySQL Clausole GROUP BY e HAVING con esempi
โก Riepilogo intelligente
Le clausole SQL GROUP BY e HAVING trasformano le righe dettagliate in report di riepilogo. GROUP BY raggruppa le righe che condividono gli stessi valori in un'unica riga per gruppo, mentre HAVING filtra tali gruppi dopo l'applicazione di funzioni di aggregazione come COUNT.

Cos'รจ la clausola GROUP BY di SQL?
La clausola GROUP BY รจ un comando SQL utilizzato per raggruppare le righe che hanno gli stessi valoriViene inserita all'interno dell'istruzione SELECT e viene normalmente utilizzata insieme alle funzioni di aggregazione per generare report riepilogativi dal database.
Ecco cosa fa: riassume i dati conservati nel database. Le query che contengono la clausola GROUP BY sono chiamate query raggruppate e restituiscono una singola riga per ogni elemento raggruppato.
Sintassi SQL GROUP BY
Ora che lo scopo della clausola รจ chiaro, esaminiamo la sintassi di una query raggruppata di base.
SELECT statements... GROUP BY column_name1[, column_name2, ...] [HAVING condition];
QUI
- "Istruzioni SELECTโฆ" รจ lo standard SELEZIONA SQL query del comando.
- "RAGGRUPPA PER nome_colonna1" รจ la clausola che esegue il gruppoping in base al nome della colonna1.
- "[, nome_colonna2, โฆ]" รจ facoltativo e rappresenta altri nomi di colonna quando il gruppoping viene fatto su piรน di una colonna.
- "[Condizione di avere]" รจ facoltativo e viene utilizzato per limitare le righe interessate dalla clausola GROUP BY. ร simile a Dove la clausola, tranne che viene applicato dopo il gruppoping.
Grouping Utilizzando una singola colonna
Il modo piรน rapido per vedere l'effetto della clausola SQL GROUP BY รจ confrontare una query non raggruppata con una raggruppata. Inizia con una query semplice che restituisce ogni voce relativa al genere nella tabella dei membri.
SELECT `gender` FROM `members`;
| genere |
|---|
| Femmina |
| Femmina |
| Maschio |
| Femmina |
| Maschio |
| Maschio |
| Maschio |
| Maschio |
| Maschio |
Vengono restituite nove righe e ogni valore viene ripetuto. Supponiamo di volere invece i valori univoci per il genere. La query seguente aggiunge la clausola GROUP BY.
SELECT `gender` FROM `members` GROUP BY `gender`;
Eseguendo lo script precedente in MySQL banco di lavoro rispetto a myflixdb ci fornisce i seguenti risultati.
| genere |
|---|
| Femmina |
| Maschio |
Si noti che sono state restituite solo due righe, perchรฉ la tabella contiene solo due tipi di genere. La clausola GROUP BY ha raggruppato tutti i membri "Maschio" e ha restituito una singola riga per essi, e ha fatto lo stesso con i membri "Femmina".
Grouping Utilizzo di piรน colonne
Grouping Un'analisi basata su una sola colonna รจ spesso troppo generica per un report reale. La clausola GROUP BY accetta un elenco di colonne separate da virgole e la combinazione dei loro valori definisce ciascun gruppo.
Supponiamo di voler ottenere un elenco di valori category_id per i film e i corrispondenti anni di uscita. Osserviamo innanzitutto l'output di questa semplice query.
SELECT `category_id`, `year_released` FROM `movies`;
| categoria_id | anno_rilasciato |
|---|---|
| 1 | 2011 |
| 2 | 2008 |
| NULL | 2008 |
| NULL | 2010 |
| 8 | 2007 |
| 6 | 2007 |
| 6 | 2007 |
| 8 | 2005 |
| NULL | 2012 |
| 7 | 1920 |
| 8 | NULL |
| 8 | 1920 |
Le righe evidenziate mostrano che il risultato contiene duplicati. Eseguendo la stessa query con GROUP BY, questi vengono rimossi.
SELECT `category_id`, `year_released` FROM `movies` GROUP BY `category_id`, `year_released`;
Eseguendo lo script precedente in MySQL L'analisi con Workbench su myflixdb fornisce i seguenti risultati, mostrati di seguito.
| categoria_id | anno_rilasciato |
|---|---|
| NULL | 2008 |
| NULL | 2010 |
| NULL | 2012 |
| 1 | 2011 |
| 2 | 2008 |
| 6 | 2007 |
| 7 | 1920 |
| 8 | 1920 |
| 8 | 2005 |
| 8 | 2007 |
La clausola GROUP BY opera sia su category_id che su year_released per identificare unica righe. Le due righe duplicate per la categoria 6 nel 2007 sono state accorpate in una sola.
Regola del pollice: Se l'ID della categoria รจ lo stesso ma l'anno di pubblicazione รจ diverso, la riga viene considerata univoca. Se l'ID della categoria e l'anno di pubblicazione sono uguali per piรน di una riga, le righe sono duplicate e ne viene visualizzata solo una.
Grouping e funzioni aggregate
Rimuovere i duplicati รจ utile, ma il vero potere del raggruppamentoping appare quando รจ abbinato a funzioni aggregate. Una funzione di aggregazione calcola un valore per ogni gruppo: COUNT conta le righe, SUM somma i valori e AVG, MIN e MAX descrivono la dispersione.
Supponiamo di voler ottenere il numero totale di membri maschi e femmine presenti nel database. Lo script seguente esegue questa operazione.
SELECT `gender`, COUNT(`membership_number`) FROM `members` GROUP BY `gender`;
Eseguendo lo script precedente in MySQL L'analisi con Workbench su myflixdb ci fornisce i seguenti risultati.
| genere | CONTA(`numero_di_iscrizione`) |
|---|---|
| Femmina | 3 |
| Maschio | 6 |
Le righe sono raggruppate in base a ciascun valore univoco del genere e il numero di righe all'interno di ciascun gruppo viene conteggiato dalla funzione di aggregazione COUNT. I nove record dei membri vengono poi raggruppati in due righe di riepilogo.
Limitare i risultati delle query utilizzando la clausola HAVING
GroupingNon sempre si desidera ottenere risultati per ogni riga di una tabella. Talvolta il report deve essere limitato a un determinato criterio, ed รจ questo il compito della clausola HAVING.
Supponiamo di voler conoscere tutti gli anni di uscita per la categoria di film con ID 8. Lo script seguente permette di ottenere questo risultato.
SELECT * FROM `movies` GROUP BY `category_id`, `year_released` HAVING `category_id` = 8;
Eseguendo lo script precedente in MySQL L'analisi con Workbench su myflixdb fornisce i seguenti risultati, mostrati di seguito.
| id_film | titolo | direttore | anno_rilasciato | categoria_id |
|---|---|---|---|---|
| 9 | Honey moonERS | John Schutz | 2005 | 8 |
| 5 | Le bambine di papร | NULL | 2007 | 8 |
Solo i film con ID categoria 8 sono stati mantenuti dalla condizione HAVING.
Attenzione: MySQL 5.7 e versioni successive abilitano la modalitร ONLY_FULL_GROUP_BY per impostazione predefinita e, in tale modalitร , SELECT * con una clausola GROUP BY viene rifiutata, perchรฉ movie_id, title e director non sono nรฉ raggruppati nรฉ aggregati. In produzione, denominare esplicitamente le colonne raggruppate, ad esempio SELEZIONA category_id, year_released DA movies GRUPPO PER category_id, year_released AVENDO category_id = 8;
DOVE vs AVERE vs GRUPPO PER vs ORDINA PER
I principianti spesso confondono queste quattro clausole, perchรฉ tutte plasmano l'insieme dei risultati. La differenza sta in quando MySQL Le seguenti clausole vengono applicate: WHERE viene eseguita prima del raggruppamento delle righe, HAVING viene eseguita dopo e ORDER BY viene eseguita per ultima.
| Clausola | Ciรฒ che fa | Quando funziona | Accetta funzioni aggregate |
|---|---|---|---|
| DOVE | Filtra le singole righe prima di qualsiasi gruppoping. | Prima di raggruppare per | Non |
| RAGGRUPPA PER | Raggruppa le righe che condividono gli stessi valori in un'unica riga per gruppo. | Dopo DOVE | Non applicabile |
| VISTA | Filtra i gruppi prodotti da GROUP BY. | Dopo il raggruppamento per | Sรฌ, ad esempio HAVING COUNT(*) > 2 |
| ORDINATO DA | Ordina le righe che sopravvivono alle clausole precedenti. | Cognome | Sรฌ, un alias aggregato puรฒ essere ordinato |
La conseguenza pratica รจ di natura prestazionale. Il filtraggio con WHERE rimuove le righe prima del gruppoping Il lavoro inizia, quindi una condizione che non dipende da un risultato aggregato va inserita in WHERE piuttosto che in HAVING.
