Group by SQL: come ottenere dati aggregati dai database

La clausola GROUP BY del linguaggio SQL è uno strumento fondamentale che permette di aggregare i dati presenti all’interno di un database relazionale, rispondendo in modo semplice e veloce a un’esigenza frequentissima nell’ambito dell’analisi dei dati.

Facciamo un esempio per chiarire meglio l’utilizzo della group by. Nel nostro database sarà sicuramente presente una tabella in cui vengono archiviate le fatture. Tramite le istruzioni Where e Join è possibile visualizzare le fatture che rispecchiano particolari requisiti, magari combinando i dati di più tabelle. Tuttavia molto spesso le attività di analisi dei dati non saranno interessate all’elenco di singole fatture, ma vogliono estrarre informazioni più generali, di più ampio respiro, aggregate sulle dimensioni di analisi del particolare business che il database descrive. Ad esempio potremmo essere interessati a rispondere a domande come “calcolare l’importo delle fatture diviso per regioni di provenienza del cliente“, oppure “calcolare l’importo delle fatture al variare del mese di vendita“. Il soggetto della richiesta è spostato dunque dalla fattura a una grandezza diversa, come la regione, il mese o un’altra colonna descrittiva.

Tutti i software e i linguaggi di programmazione che si interfacciano con i dati mettono a disposizione funzionalità per rispondere a questo genere di domande. Ad esempio su Microsoft Excel potremmo creare una tabella Pivot (a questo link trovi un mio approfondimento in merito), su Python abbiamo a disposizione la libreria Pandas, su MongoDB possiamo usare il metodo aggregate. L’SQL non è da meno: tramite la parola chiave GROUP BY e alcune funzioni di aggregazione possiamo scrivere del codice semplice, efficace, di facile manutenzione e veloce per raggruppare i dati e analizzarli da più dimensioni differenti.

Come scrivere una clausola GROUP BY in SQL

La lingua italiana è molto vasta e uno stesso concetto può essere espresso in maniera diversa. Uno sviluppatore SQL che deve “aggregare i dati per regione”, “estrarre i dati divisi per regione”, “raggruppare per regione”, “riportare l’output per ogni regione” dovrà scrivere una query contenente l’istruzione Group By seguita dalla colonna corrispondente alla dimensione di analisi richiesta (in questo caso la regione).

A questo punto può seguire quella che a me piace chiamare nei miei corsi “la regola d’oro” che risulta applicabile in una percentuale di casi molto vicina al cento per cento:

ciò che scriviamo dopo la group by, deve essere copiato e incollato nella select. A questo punto, nella select posso aggiungere solamente funzioni di aggregazione applicate ad altre colonne

Con funzioni di aggregazioni la maggior parte delle volte si intende semplicemente una di queste cinque funzioni:

  • count;
  • sum;
  • avg;
  • min;
  • max.

Facciamo un esempio concreto. Dobbiamo riportare l’importo complessivo delle fatture per ogni anno. Partiamo scrivendo la struttura classica di una query:

SELECT
FROM
WHERE
GROUP BY

Iniziamo valorizzando la clausola From con la tabella contenente le informazioni richieste (immaginiamo si chiami Fatture) ed eliminiamo la clausola Where in quanto non è richiesto nessun filtro sui dati. Scriveremo dunque

SELECT
FROM      Fatture
GROUP BY

Il fatto che la domanda ci chieda i dati divisi per anno, o analogamente per ogni anno, aggregati per anno, divisi per anno, ci deve immediatamente portare a scrivere questa informazione nella clausola Group by:

SELECT
FROM     Fatture
GROUP BY YEAR(DataFattura);

A questo punto applico la regola d’oro: faccio in primo luogo copia e incolla nella Select di quanto scritto nella Group by:

SELECT   YEAR(DataFattura) 
FROM     Fatture
GROUP BY YEAR(DataFattura);

e valuto la possibilità di aggiungere solo delle funzioni di aggregazioni. In questo caso, per rispondere alla richiesta, aggiungo la somma (SUM) della colonna Importo.

SELECT   YEAR(DataFattura), 
         SUM(Importo)
FROM     Fatture
GROUP BY YEAR(DataFattura);

A patto di fornire un alias alle mie colonne nella select, la query è terminata!

Query SQL per ottenere dati aggregati

La GROUP BY può essere utilizzata anche in query più complesse che richiedono di utilizzare anche altre clausole delle SQL come la WHERE o la JOIN. Supponiamo ad esempio di voler calcolare “l’importo totale delle fatture del 2019 al variare della regione di residenza del cliente”.

In questo caso avremo bisogno di utilizzare anche una WHERE e una JOIN in questo modo:

SELECT 
  C.RegioneResidenza,  
  SUM(F.Importo) AS Importo
FROM Fatture AS F
INNER JOIN Clienti AS C
  ON F.IdCliente = C.IdCliente
WHERE  YEAR(F.DataFattura) = 2019
GROUP BY C.RegioneResidenza;

Sul database SQL Server possiamo inoltre combinare la GROUP BY con l’ORDER BY e la clausola TOP per risolvere facilmente problemi come “riportare l’anno con la somma degli importi maggiore”. Ecco la relativa query SQL.

SELECT TOP 1 
   YEAR(DataFattura) AS Anno, 
   SUM(Importo) AS Fatturato
FROM Fatture
GROUP BY YEAR(DataFattura)
ORDER BY Fatturato DESC;

Utilizzare più colonne nella clausola GROUP BY

Possiamo ottenere delle viste aggregate dei dati anche su più di una colonna o di un’espressione. Consideriamo ad esempio la query SQL seguente:

SELECT 
   YEAR(DataFattura) AS Anno, 
   MONTH(DataFattura) AS Mese,
   SUM(Importo) AS Fatturato
FROM Fatture
GROUP BY 
    YEAR(DataFattura),
    MONTH(DataFattura);

Con questa query calcoliamo la somma degli importi delle fatture raggruppate per ogni combinazione di anno e mese presente nella colonna DataFattura.

GROUP BY e HAVING in query SQL

L’HAVING è una clausola SQL utilizzabile per effettuare dei filtri sull’output di una GROUP BY. Ad esempio la query seguente estrae “gli anni con almeno tre fatture“:

SELECT 
   YEAR(DataFattura) AS Anno, 
   COUNT(*) AS NumeroFatture
FROM  Fatture
GROUP BY YEAR(DataFattura)
HAVING COUNT(*) >= 3;

Occorre fare attenzione a non confondere le tipologie di filtri da inserire nell’HAVING con le più classiche condizioni da inserire nella WHERE. Una classica domanda da colloquio di lavoro è proprio quella di spiegare la differenza tra Where e Having. Qui trovi un approfondimento in merito.

Continua a imparare

Torna in alto
Torna su