Torna all'elenco degli articoli Articoli
Tempo di lettura: 12 minuti

Come usare SUM() con GROUP BY: Una guida dettagliata con 8 esempi

Esplora alcuni esempi reali di utilizzo di SUM() e GROUP BY in SQL, dai più elementari ai più sofisticati.

SUM() è una funzione aggregata SQL che calcola la somma dei valori dati. GROUP BY è una clausola SQL che suddivide le righe in gruppi e calcola una funzione aggregata per ogni gruppo. Utilizzando queste due funzioni insieme, è possibile calcolare le somme totali di un gruppo di righe.

In questo articolo vedremo 8 diversi esempi di come sia possibile combinare SUM() e GROUP BY per creare molti report diversi. Parleremo dei casi d'uso più elementari e tratteremo alcuni scenari complessi.

Il modo migliore per rinfrescare le vostre conoscenze di SQL, comprese quelle di SUM() e GROUP BY, è il nostro sito interattivo SQL Practice Set. Contiene 88 esercizi interattivi che coprono diversi argomenti di SQL. Il corso è perfetto per la preparazione ai colloqui o per un ripasso prima di un esame SQL.

Esempio 1: Uso di base di SUM() e GROUP BY in SQL

Vediamo un esempio di come la funzione SUM() lavora insieme a GROUP BY:

SELECT 
  country, 
  SUM(quantity) AS total_quantity
FROM orders
GROUP BY country;

La query restituisce un elenco di tutti i paesi trovati nella tabella orders insieme alla somma totale delle quantità ordinate per ciascun Paese. Le righe della tabella orders sono divise in gruppi (un gruppo per ogni paese) e il database somma i valori delle quantità per ogni paese.

countrytotal_quantity
United States37
United Kingdom43
Mexico12
New Zealand30

Analisi dettagliata dell'esempio 1

Analizziamo questo esempio in dettaglio.

Ecco i dati della tabella orders tabella. Questa tabella è comune in un sistema di e-commerce; oltre al paese di destinazione della merce e alla quantità ordinata, include i dati del venditore che ha preso l'ordine, lo SKU del prodotto, la data dell'ordine e l'indirizzo del cliente.

order_noorder_datesalespersonproduct_skuquantityamountaddresscountry
10948022023-04-03Meghan99005500346410845.2528 Morningview Lane New YorkUnited States
10948032023-04-04Stephen99004800642712705.54666 Lawman Avenue AlexandriaUnited States
10948042023-04-05Arthur77006100721915914.423445 Queens Lane LynchburgUnited States
10948052023-04-06Stephen990055003464181012.6693 Iffley Road BrockbridgeUnited Kingdom
10948062023-04-07Meghan990048006427252045.7299 Felix Lane ShirleyUnited Kingdom
10948072023-04-08Arthur770061007219Av. Cantera No. 954 Baja CaliforniaMexico
10948082023-04-05Meghan990055003464Sanchez Marmol 408 TabascoMexico
10948092023-04-06Stephen990048006427197 Glencairn Street DunedinNew Zealand
10948102023-04-04Arthur77006100721916842.06139 Petherick Crescent WellingtonNew Zealand
10948112023-04-09Arthur990055003464Rio Reforma 1730 JaliscoMexico
10948122023-04-08Meghan99004800642712912.45Municipal 114 VeracruzMexico
10948132023-04-06Stephen77006100721914799.45105 Queen Elizabeth II Drive WakapuakaNew Zealand

La tabella ordini verrà utilizzata in questo articolo.

La funzione SUM() in SQL

La funzione SUM() è una delle funzioni aggregate di SQL. Le funzioni aggregate in SQL restituiscono un singolo valore per un insieme di righe. La funzione SUM() restituisce la somma degli argomenti forniti alla funzione. Esistono altre funzioni aggregate in SQL, ma in questo articolo ci concentreremo solo su SUM().

Quando aggiungiamo SUM() alla query...

SELECT SUM(quantity)
FROM orders;

... otterremo un solo valore, risultante dalla somma di tutti i valori delle quantità:

SUM(quantity)
122

Si noti che la funzione SUM() ignora i valori NULL. Essi vengono trattati come 0 nel calcolo. Per ulteriori informazioni sulla funzione SUM(), potete leggere questa spiegazione completa della funzione SQL SUM().

La funzione SUM(), come altre funzioni di aggregazione, viene solitamente utilizzata con la clausola GROUP BY.

La clausola GROUP BY in SQL

La clausola GROUP BY viene utilizzata per calcolare le statistiche di un gruppo di righe; le righe vengono suddivise in gruppi in base ai valori di una o più colonne. L'istruzione SELECT con GROUP BY restituisce una singola riga per ciascun gruppo distinto definito nella clausola GROUP BY.

Torniamo alla nostra query di esempio:

SELECT 
  country, 
  SUM(quantity) AS total_quantity
FROM orders
GROUP BY country;

Le righe della tabella orders sono suddivise in gruppi in base al valore della colonna country grazie a questa riga: GROUP BY country. Indica al database di inserire le righe con lo stesso valore di country in un unico gruppo.

order_noorder_datesalespersonproduct_skuquantityamountaddresscountry
10948072023-04-08Arthur770061007219Av. Cantera No. 954 Baja CaliforniaMexico
10948082023-04-05Meghan990055003464Sanchez Marmol 408 TabascoMexico
10948112023-04-09Arthur990055003464Rio Reforma 1730 JaliscoMexico
10948122023-04-08Meghan99004800642712912.45Municipal 114 VeracruzMexico
10948092023-04-06Stephen990048006427197 Glencairn Street DunedinNew Zealand
10948102023-04-04Arthur77006100721916842.06139 Petherick Crescent WellingtonNew Zealand
10948132023-04-06Stephen77006100721914799.45105 Queen Elizabeth II Drive WakapuakaNew Zealand
10948052023-04-06Stephen990055003464181012.6693 Iffley Road BrockbridgeUnited Kingdom
10948062023-04-07Meghan990048006427252045.7299 Felix Lane ShirleyUnited Kingdom
10948022023-04-03Meghan99005500346410845.2528 Morningview Lane New YorkUnited States
10948032023-04-04Stephen99004800642712705.54666 Lawman Avenue AlexandriaUnited States
10948042023-04-05Arthur77006100721915914.423445 Queens Lane LynchburgUnited States

Le righe del Messico vengono inserite in un gruppo, quelle della Nuova Zelanda in un altro gruppo e così via. La funzione SUM() viene quindi applicata ai valori delle quantità in ciascun gruppo. La somma per gli Stati Uniti è la somma di 10, 12 e 15, che dà come risultato 37. La somma per il Regno Unito è la somma di 18 e 25, con il risultato di 43, ecc.

Ecco di nuovo il risultato della nostra query. Si può notare che ogni riga contiene la somma dei valori delle quantità nel gruppo corrispondente.

countrytotal_quantity
United States37
United Kingdom43
Mexico12
New Zealand30

La clausola GROUP BY è particolarmente utile quando si vogliono ottenere informazioni di riepilogo da tabelle con un numero eccessivo di righe da esaminare una per una. Per ulteriori informazioni, leggete una spiegazione completa della clausola SQL GROUP BY o questo articolo che spiega GROUP BY in SQL.

Esempio 2: Calcolo di 2 somme e raggruppamento per 2 colonne

Nell'esempio precedente abbiamo visto come utilizzare SUM() e GROUP BY per raggruppare una serie di dati in base alla colonna Paese e ottenere la quantità totale per ciascun Paese separatamente. Con GROUP BY è anche possibile raggruppare per più colonne e calcolare più somme in una query.

Se vogliamo conoscere tutte le combinazioni di country e salesperson nella tabella e ottenere il totale delle quantità ordinate e i relativi importi per ogni combinazione, dobbiamo usare SUM() e GROUP BY.

Ecco la query:

SELECT 
  country, 
  salesperson, 
  SUM(quantity) AS qtyTotal,
  SUM(amount) AS amntTotal
FROM orders
GROUP BY country, salesperson;

Sulla base della tabella precedente, questa query produce i seguenti dati:

countrysalespersonqtyTotalamntTotal
United StatesMeghan10845.25
United StatesStephen12705.50
United StatesArthur15914.42
United KingdomStephen181012.65
United KingdomMeghan252045.72
MexicoArthurNULLNULL
MexicoMeghan12912.45
New ZealandStephen14799.45
New ZealandArthur16842.06

Abbiamo due espressioni che utilizzano la funzione SUM() nella query: una calcola la quantità totale e l'altra l'importo totale. Inoltre, raggruppiamo per due colonne: country e salesperson.

Internamente, il motore del database esegue la seguente procedura:

  1. Crea un insieme di risultati dalla tabella specificata nella clausola FROM, raggruppando le righe per ogni combinazione di valori delle colonne specificate nella clausola GROUP BY. Nel nostro esempio, le righe con lo stesso valore di country e salesperson vengono raggruppate: c'è una riga per le vendite di Meghan negli Stati Uniti, una riga per le vendite di Stephen negli Stati Uniti, ecc.
  2. Per ogni riga dell'insieme di risultati creato nel passaggio precedente, calcola la somma di ogni colonna racchiusa in SUM() Nel nostro esempio, calcola la somma delle colonne quantity e la somma delle colonne amount.
  3. Restituisce il set di risultati con le somme.

Se necessario, è possibile raggruppare per più di due colonne. Per informazioni sul raggruppamento per più colonne, consultare l'articolo Come raggruppare per più colonne in SQL.

Esempio 3: Uso di una condizione WHERE con SUM e GROUP BY

È possibile utilizzare una condizione WHERE nella query con SUM() e GROUP BY. In questo caso, il motore di database modifica la procedura vista sopra per restituire i risultati della query. Applica la clausola WHERE nel passo 1 della procedura. Quindi, l'insieme dei risultati iniziali sarà composto da quelle righe che soddisfano la condizione WHERE.

Le colonne coinvolte nella condizione WHERE possono essere qualsiasi colonna della tabella. Non importa se sono elencate o meno nella clausola GROUP BY o se vengono restituite come risultato della query.

Seguendo il nostro esempio, si potrebbe usare una qualsiasi colonna della tabella orders ad esempio product_sku o order_date. Siamo interessati agli ordini del prodotto con SKU 990048006427 effettuati tra il 7 aprile 2023 e l'8 aprile 2023.

SELECT 
  country, 
  salesperson, 
  SUM(quantity) AS qtyTotal,
  SUM(amount) AS amntTotal
FROM orders
WHERE 
  product_sku = '990048006427' 
  AND order_date BETWEEN '2023-04-07' AND '2023-04-08'
GROUP BY country, salesperson;

Per risolvere questa query, il motore del database creerà prima un set di risultati temporanei dalla tabella orders che soddisfa le condizioni della clausola WHERE. Da questo insieme di risultati, prenderà tutte le combinazioni delle colonne country e salesperson. Per ogni combinazione, calcolerà le somme di quantity e amount.

countrysalespersonqtyTotalamntTotal
United KingdomMeghan252045.72
MexicoMeghan12912.45

Si noti che quando si confronta il risultato con l'Esempio 2, si includono solo gli ordini effettuati tra il 7 aprile 2023 e l'8 aprile 2023 per il prodotto 990048006427. Ad esempio, non ci sono righe per le vendite di Meghan negli Stati Uniti, poiché non ha venduto questo prodotto nei due giorni di aprile.

Esempio 4: Utilizzo della clausola ORDER BY con SUM e GROUP BY

Se aggiungiamo anche una clausola ORDER BY alla query costruita con SUM() e GROUP BY, il motore del database dovrà fare un po' di lavoro in più. Aggiunge un'ulteriore fase alle tre descritte in precedenza; questa fase consiste nell'ordinare i risultati in base ai criteri specificati nella clausola ORDER BY.

Ad esempio, si potrebbero ordinare i risultati in base alla somma di amount, facendo riferimento al suo alias amntTotal. Si potrebbe anche specificare l'espressione completa SUM(amount):

SELECT 
  country, 
  salesperson, 
  SUM(quantity) AS qtyTotal, 
  SUM(amount) AS amntTotal
FROM orders
GROUP BY country, salesperson
ORDER BY amntTotal DESC;

In questo esempio, aggiungiamo la clausola DESC in modo che i risultati siano ordinati dal più alto al più basso.

countrysalespersonqtyTotalamntTotal
United KingdomMeghan252045.72
United KingdomStephen181012.66
United StatesArthur15914.42
MexicoMeghan12912.45
United StatesMeghan10845.25
New ZealandArthur16842.06
New ZealandStephen14799.45
United StatesStephen12705.5
MexicoArthurNULLNULL

Esempio 5: Somma di espressioni

Oltre a essere applicata a singole colonne, la funzione SUM può essere applicata anche a espressioni che restituiscono valori numerici. Si supponga di avere una colonna unit_price invece di una colonna importo. L'importo dell'ordine risulterebbe dalla moltiplicazione di quantity per unit_price.

Affinché l'SQL SUM GROUP BY restituisca una somma degli importi ordinati in questo caso, dovremo applicare la funzione SUM() all'espressione quantity * unit_price:

SELECT 
  country, 
  salesperson, 
  SUM(quantity) AS qtyTotal,
  SUM(quantity * unit_price) AS amntTotal
FROM orders
GROUP BY country, salesperson;

Il risultato della query sarà lo stesso dell'Esempio 2:

countrysalespersonqtyTotalamntTotal
United StatesMeghan10845.25
United StatesStephen12705.50
United StatesArthur15914.42
United KingdomStephen181012.65
United KingdomMeghan252045.72
MexicoArthurNULLNULL
MexicoMeghan12912.45
New ZealandStephen14799.45
New ZealandArthur16842.06

La procedura eseguita dal motore del database sarebbe leggermente diversa. Per ogni gruppo, calcolerebbe prima il valore dell'espressione quantity * unit_price e poi calcolerebbe le somme utilizzando i valori calcolati.

Esempio 6: Valori nulli nella funzione SUM()

Quando si utilizza la funzione SUM() in SQL, NULLs viene ignorato e non viene incluso nel calcolo del totale. Se una riga della tabella orders tabella avesse valori NULL nelle colonne quantity o amount, questi verrebbero ignorati dalla funzione SUM(). Fa eccezione il caso in cui tutti i valori siano NULL per una qualsiasi delle colonne, nel qual caso la funzione SUM() restituirà anche NULL.

Questa avvertenza riguarda la combinazione SUM() e GROUP BY. Se esistono alcune combinazioni di valori delle colonne GROUP BY in cui tutti i valori totalizzati sono NULL, allora SUM() restituirà anche NULL per quella combinazione di valori.

Nella nostra tabella degli ordini di esempio, tutte le righe per country='Mexico' e salesperson='Arthur' hanno un valore NULL in quantità e importo. Per questo motivo, il risultato di SUM() e GROUP BY restituisce NULL nella somma di quantità e importo per country = 'Mexico' e salesperson = 'Arthur'. Tuttavia, né Arthur né Mexico sono NULL in qualsiasi altra combinazione.

Date un'occhiata:

SELECT 
  country, 
  salesperson, 
  SUM(quantity) AS qtyTotal,
  SUM(amount) AS amntTotal
FROM orders
WHERE country = 'Mexico' AND Salesperson = 'Arthur'
GROUP BY country, salesperson;
countrysalespersonqtyTotalamntTotal
MexicoArthurNULLNULL

Se venisse inserita una nuova riga per country = 'Mexico' e salesperson = 'Arthur' con valori nonNULL in quantity e amount, il resto dei valori di NULL verrebbe ignorato nel totale. I risultati di SUM() includeranno solo i valori che non hanno NULLs nelle colonne sommate.

Esempio 7: Conversione dei valori NULL in zeri

Abbiamo visto che la funzione SUM() restituisce NULL se tutti i valori della colonna sommata sono NULL. Se c'è un solo valore nonNULL, il resto dei valori NULL viene ignorato, cioè trattato come se fosse zero.

Questo può essere difficile da spiegare quando si fa storytelling di dati. Vogliamo evitare che la parola "NULL" compaia in una casella di risultato dove dovrebbe comparire un numero (causando così confusione al nostro pubblico). In questi casi, è conveniente convertire i valori di NULL in zeri. A tale scopo, è possibile utilizzare la funzione COALESCE. Essa converte i valori di NULL in una colonna in un valore prestabilito, di solito zero, anche se è possibile utilizzare altri valori.

Nel nostro esempio, non vogliamo correre il rischio che i valori di NULL in quantity o amount facciano apparire il testo "NULL" nei risultati. Si possono racchiudere queste colonne nella funzione COALESCE e inviare il risultato come parametro della funzione SUM():

SELECT 
  country, 
  salesperson, 
  SUM(COALESCE(quantity, 0)) AS qtyTotal,
  SUM(COALESCE(amount, 0)) AS amntTotal
FROM orders
GROUP BY country, salesperson;

In questo modo, tutti i NULLs nelle colonne sommate appariranno come zeri.

countrysalespersonqtyTotalamntTotal
United StatesMeghan10845.25
United StatesStephen12705.50
United StatesArthur15914.42
United KingdomStephen181012.65
United KingdomMeghan252045.72
MexicoArthur00.00
MexicoMeghan12912.45
New ZealandStephen14799.45
New ZealandArthur16842.06

Si noti che la riga relativa alle vendite di Arthur in Messico ora mostra 0 invece di NULL.

Esempio 8: SOMMA() con condizionali

A volte si desidera che la combinazione GROUP BY SUM() consideri solo i dati che soddisfano determinate condizioni.

Continuando con il nostro esempio, supponiamo che ogni ordine abbia una colonna di tipo BIT chiamata delivered che indica se l'ordine è stato consegnato o meno. Potremmo volere che i risultati delle nostre sommatorie siano divisi in due: un totale di prodotti consegnati e un totale di prodotti non consegnati. Per risolvere questo problema, utilizzare CASE WHEN all'interno della funzione SUM() per valutare il contenuto della colonna delivered:

SELECT 
  country,
  SUM(CASE 
    WHEN delivered = 1 THEN quantity 
    ELSE 0 END) AS qtyTotalDelivered,
  SUM(CASE 
    WHEN delivered = 0 THEN quantity 
    ELSE 0 END) AS qtyTotalNotDelivered
FROM orders
GROUP BY country;

L'istruzione CASE WHEN è simile all'istruzione IF in molti linguaggi di programmazione; aggiunge una certa logica al flusso della nostra query valutando una condizione dichiarata. La condizione viene indicata dopo WHEN. Se la condizione è soddisfatta, viene restituito il valore dopo THEN. Se la condizione non è soddisfatta, viene restituito il valore dopo ELSE.

CASE 
    WHEN delivered = 1 THEN quantity 
    ELSE 0 END

In questa espressione, si restituisce la colonna quantity per i prodotti consegnati. Per gli altri prodotti, restituiamo 0.

Ecco il risultato della query:

countryqtyTotalDeliveredqtyTotalNotDelivered
United States2215
United Kingdom1825
Mexico12NULL
New Zealand1416

Per ulteriori informazioni su come utilizzare CASE WHEN con SUM e GROUP BY, consultare il nostro blog.

Esercitarsi a usare SUM() con GROUP BY nelle query SQL

In questo articolo abbiamo visto otto esempi di come combinare SUM() e GROUP BY nelle query SQL. La nostra tabella orders pur avendo solo poche righe, rappresenta situazioni reali.

Nel vostro lavoro, incontrerete spesso situazioni simili a quelle presentate, ma le vostre tabelle saranno popolate da molte più righe. Dovrete quindi utilizzare tutte le possibili varianti di SUM() e GROUP BY per dimostrare che i risultati delle vostre interrogazioni sono legittimi.

Approfittate del nostro SQL Practice Set corso e SQL Practice per affinare le vostre competenze in SQL. Ricordate: L'aspetto più critico del lavoro di un analista di dati è che le informazioni fornite siano affidabili al 100%.