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

Funzioni GROUP BY e aggregate: Una panoramica completa

Le funzioni GROUP BY e aggregate di SQL sono essenziali per l'aggregazione dei dati, per l'analisi dei dati e per la creazione di report. Esploriamole insieme!

In SQL, le funzioni GROUP BY e aggregate sono una delle caratteristiche più popolari del linguaggio. L'aggregazione dei dati è fondamentale per l'analisi dei dati e la creazione di report; per dare un senso a tutti i dati di un set di dati, spesso è necessario aggregarli.

Ma che cos'è l'aggregazione dei dati? In parole povere, si tratta di raggruppare i dati in base a valori comuni ed eseguire un calcolo per ciascun gruppo di dati. Ad esempio, si può raggruppare un elenco di cani in base alla loro razza e poi utilizzare un calcolo per determinare l'altezza media di ciascuna razza. Questo compito è reso possibile dalla clausola GROUP BY e dalla funzione aggregata AVG().

Se avete bisogno di rinfrescare le vostre conoscenze su GROUP BY, il nostro corso è l'ideale. SQL per principianti corso è l'ideale. Contiene 129 esercizi interattivi che si possono completare in circa 10 ore. Vengono trattati argomenti come il filtraggio dei dati, l'uso degli operatori logici, l'unione e l'uso degli operatori di set.

La sintassi di base di GROUP BY con aggregati

GROUP BY è una clausola di SQL che organizza i dati con gli stessi valori in gruppi. Il raggruppamento avviene per colonna/e, dove tutte le righe con lo stesso valore in quella colonna appartengono a un gruppo. È quindi possibile eseguire calcoli di riepilogo, come il conteggio, la somma o la media dei valori, per ciascun gruppo. Ad esempio, è possibile utilizzare GROUP BY per calcolare il numero di dipendenti in un reparto, il salario totale o il salario medio per reparto, ecc.

La sintassi di GROUP BY con una funzione aggregata è la seguente:

SELECT column1, 
        column2, 
        ..., 
        aggregate_function(column_name)
FROM table_name
WHERE filtering_condition
GROUP BY column1, column2, …
HAVING filtering_condition;

La funzione aggregata viene scritta nell'istruzione SELECT e il risultato della funzione viene visualizzato come colonna aggiuntiva.

La clausola GROUP BY contiene le colonne in base alle quali si desidera raggruppare l'output. Questa clausola viene spesso utilizzata con le clausole WHERE e HAVING per il filtraggio. Nella sintassi, WHERE viene prima di GROUP BY, mentre HAVING viene dopo. (Inoltre, a volte i dati contengono NULLs, per cui è importante sapere come GROUP BY tratta i NULL.

Un esempio di GROUP BY in azione è mostrato nella GIF seguente.

Come funziona SQL GROUP BY

Questo esempio di base raggruppa i dati per regista e mostra il numero di film realizzati da ciascuno.

Funzioni aggregate di SQL

Le funzioni aggregate di SQL vengono utilizzate quando si desidera eseguire calcoli sui dati e restituire un singolo valore.

Le funzioni aggregate più comuni in SQL sono:

  • COUNT() - Conta le righe nella colonna indicata.
  • SUM() - Restituisce la somma di tutti i valori.
  • AVG() - Calcola la media di un gruppo di valori.
  • MIN() - Restituisce il minimo (il più basso) dei valori indicati.
  • MAX() - Restituisce il massimo (il più alto) dei valori dati.

Consultate le nostre guide su come utilizzare queste funzioni per calcolare gli aggregati per l'intera tabella:

È importante notare che la funzione COUNT() ha diverse varianti di utilizzo:

  • COUNT(*) conta tutte le righe in un set di risultati, compresi i valori NULL e i duplicati.
  • COUNT(expression) conta i valori non NULL in un insieme di risultati.
  • COUNT(DISTINCT) conta i valori distinti e ignora i duplicati.

Maggiori dettagli nella guida Qual è la differenza tra COUNT(*), COUNT(1), COUNT(column) e COUNT(DISTINCT)?

Uso di GROUP BY con le funzioni aggregate di SQL

Utilizzerò la tabella albums per mostrare come le funzioni aggregate e GROUP BY lavorano insieme. Lo script per la creazione della tabella è qui.

Questa tabella contiene dati sugli album musicali. Ecco un'istantanea:

idartistalbumrelease_yearlengthlabel
1Grant GreenThe Latin Bit19630:38:56Blue Note Records
2AC/DCHigh Voltage19760:44:23Atlantic Records
3Brother Jack McDuffTo Seek a New Home19700:33:12Blue Note Records
4Grant GreenGreen Is Beautiful19700:37:33Blue Note Records
5Wayne ShorterMoto Grosso Feio19740:42:22Blue Note Records

Esempio 1: COUNT() con GROUP BY

Ecco un esempio di codice che conta il numero di album per etichetta:

SELECT label,
	 COUNT(*) AS number_of_albums
FROM albums
GROUP BY label; 

Seleziono l'etichetta e uso COUNT(*) per trovare il numero di album. L'asterisco (*) è un'abbreviazione per il conteggio di tutte le righe. Quando si raggruppa l'output per etichetta, COUNT() mostra il numero di album per etichetta.

Ecco l'output:

labelnumber_of_albums
Atlantic Records13
Blue Note Records12
Stax Records14

Ulteriori letture:

Esempio 2: SUM() con GROUP BY

Il codice seguente somma le lunghezze degli album per mostrare il totale della musica disponibile per artista:

SELECT artist,
	 SUM(length) AS total_music_available
FROM albums
GROUP BY artist;

La funzione SUM() viene applicata alla colonna length e il risultato viene raggruppato per artista.

Questo è il risultato del codice:

artisttotal_music_available
Isaac Hayes6:30:02
Otis Redding1:34:09
Brother Jack McDuff1:58:11
Aretha Franklin1:47:07
Grant Green3:10:11
John Prine1:21:57
Led Zeppelin3:32:07
Wayne Shorter2:38:02
Albert King3:08:28
AC/DC2:05:23

Ulteriori letture:

Esempio 3: AVG() con GROUP BY

Questo codice calcola la lunghezza media degli album di ciascun artista:

SELECT artist,
	 AVG(length) AS average_album_length
FROM albums
GROUP BY artist; 

Per ottenere il risultato desiderato, è necessario utilizzare AVG() sulla colonna length e raggruppare l'output per artist.

Ecco come appare l'output:

artistaverage_album_length
Isaac Hayes1:05:00
Otis Redding0:31:23
Brother Jack McDuff0:39:24
Aretha Franklin0:35:42
Grant Green0:38:02
John Prine0:40:59
Led Zeppelin0:42:25
Wayne Shorter0:39:31
Albert King0:37:42
AC/DC0:41:48

Ulteriori letture:

Esempio 4: MIN() e MAX() con GROUP BY

Troviamo la lunghezza dell'album più breve e quella più lunga per ogni anno:

SELECT release_year,
	 MIN(length) AS minimum_album_length,
	 MAX(length) AS maximum_album_length
FROM albums
GROUP BY release_year
ORDER BY release_year; 

Come negli esempi precedenti, le funzioni aggregate vengono utilizzate sulla colonna length; MIN() per l'album più breve e MAX() per quello più lungo.

Il risultato è raggruppato per anno di pubblicazione.

Ho anche aggiunto la clausola ORDER BY per ordinare l'output dal primo all'ultimo anno in modo da renderlo più leggibile.

Ecco l'output del codice:

release_yearminimum_album_lengthmaximum_album_length
19620:34:490:34:49
19630:38:560:38:56
19640:30:170:30:17
19650:32:220:42:45
19670:32:510:41:08
19680:29:300:29:30
19690:31:300:46:00
19700:33:120:43:04
19710:42:371:33:38
19720:37:500:44:46
19730:40:571:43:10
19740:42:220:46:00
19760:39:590:44:23
19770:41:010:41:01

Ulteriori letture:

Tecniche avanzate di GROUP BY

La sezione precedente ha trattato le basi dell'utilizzo delle funzioni aggregate di SQL e di GROUP BY. Dopo aver posto queste basi, possiamo ora esplorare alcune tecniche avanzate di GROUP BY.

Filtrare i risultati aggregati con HAVING

Per filtrare i risultati aggregati, è necessario utilizzare la clausola HAVING. La sua sintassi è mostrata qui:

SELECT column1, 
       column2, 
       ..., 
       aggregate_function(column_name)
FROM table_name
GROUP BY column1, column2, …
HAVING filtering_condition;

HAVING confronta i valori aggregati con la condizione di filtraggio e restituisce solo i valori che soddisfano tale condizione. Per saperne di più, consultate il nostro articolo sulla clausola HAVING.

Vi mostriamo un esempio. Il codice seguente calcola la lunghezza media degli album per artista, ma mostra solo quelli la cui lunghezza media è inferiore a 40 minuti.

SELECT artist,
	 AVG(length) AS average_album_length
FROM albums
GROUP BY artist
HAVING AVG(length) < '00:40:00';

Ho utilizzato la funzione AVG() proprio come ho fatto in precedenza. La clausola HAVING è nuova. Per filtrare i dati nel modo richiesto, ho scritto in HAVING lo stesso calcolo della media che appare in SELECT. Poi, uso l'operatore di confronto "meno di" (<) per confrontare ogni risultato raggruppato con un valore (in questo caso, 40 minuti). Questo valore è racchiuso tra virgolette singole (''). Il valore tra le virgolette deve essere scritto nel formato HH:MM:SS (ore:minuti:secondi), perché i valori della colonna length sono di tipo INTERVAL.

Ecco l'output:

artistaverage_album_length
Otis Redding0:31:23
Brother Jack McDuff0:39:24
Aretha Franklin0:35:42
Grant Green0:38:02
Wayne Shorter0:39:31
Albert King0:37:42

Il principio è lo stesso indipendentemente dalla funzione di aggregazione utilizzata, ma ecco i ricettari per aiutarvi con altre funzioni:

Raggruppamento per più colonne

Finora ho raggruppato i dati in base a una sola colonna. Tuttavia, è anche possibile raggruppare per due o più colonne.

Non è complicato: È sufficiente elencare tutte le colonne di raggruppamento in GROUP BY e separarle con delle virgole.

In questo modo, si raggruppa per i valori delle colonne, ma anche per la combinazione dei valori di tutte le colonne di raggruppamento. Se il valore A è presente nella colonna_1 e il valore B nella colonna_2, questo è un gruppo. Se ci sono, ad esempio, i valori A nella colonna_1 e C nella colonna_2, si formerà un altro gruppo, nonostante i valori della colonna_1 siano gli stessi dell'esempio precedente.

Esempio

Il codice seguente mostra il numero di album dell'artista e l'anno di pubblicazione:

SELECT artist,
	 release_year,
	 COUNT(*) AS number_of_albums
FROM albums
GROUP BY artist, release_year
ORDER BY artist, release_year;

Utilizzo COUNT(*) per trovare il numero di album. Il risultato è raggruppato per artista e anno di pubblicazione. Come si può vedere, queste sono esattamente le colonne di GROUP BY e sono separate da una virgola.

Per rendere l'output più leggibile, ho ordinato i dati per artista in ordine alfabetico e dal primo all'ultimo anno di pubblicazione.

Questa è l'istantanea dell'output:

artistrelease_yearnumber_of_albums
AC/DC19762
AC/DC19771
Albert King19621
Albert King19671
Albert King19691
Albert King19721
Albert King19741
Aretha Franklin19671
Aretha Franklin19681
Aretha Franklin19721
Brother Jack McDuff19692
Brother Jack McDuff19701

Due funzioni aggregate in una sola query

È anche possibile scrivere una query con due funzioni aggregate. No, non è come pensate: non si scrive una funzione aggregata all'interno di un'altra. Questo non è possibile in SQL.

Due funzioni aggregate in una query possono significare due cose:

  1. Approccio semplice: Utilizzo di due funzioni aggregate in due colonne dello stesso SELECT.
  2. Approccio avanzato: Utilizzo del risultato di una funzione aggregata in un'altra funzione aggregata.

Una query, due funzioni aggregate: L'approccio semplice

L'approccio semplice si ha quando si hanno due funzioni aggregate in due colonne aggregate diverse in uno stesso SELECT. Può trattarsi della stessa funzione applicata a colonne diverse, di funzioni diverse utilizzate sulla stessa colonna o di funzioni diverse utilizzate su colonne diverse. Non ha importanza; il punto è che ci sono due aggregazioni in una query. Queste aggregazioni non "comunicano", cioè non dipendono in alcun modo l'una dall'altra.

Esempio

Nell'esempio, utilizzerò la tabella package_deliveries con lo script collegato qui.

La tabella mostra informazioni sul numero di pacchi consegnati ogni giorno in diverse città.

Ecco le prime sei righe della tabella:

iddate_of_deliverynumber_of_packagescity_of_deliverycountry_of_delivery
12024-03-0149KrakowPoland
22024-03-01528WarsawPoland
32024-03-01158GdanskPoland
42024-03-0128RijekaCroatia
52024-03-0197SplitCroatia
62024-03-0164ZagrebCroatia

Il codice sottostante calcola il numero totale e medio di pacchi per città.

SELECT city_of_delivery,
	 SUM(number_of_packages) AS total_number_of_packages,
	 AVG(number_of_packages) AS average_number_of_packages
FROM package_deliveries
GROUP BY city_of_delivery;

Si può notare che la query ha due aggregati: uno con SUM() e uno con AVG(). Non importa quante funzioni aggregate si scrivono nella query. L'unica cosa importante è che ogni aggregazione venga trattata come una riga di codice o una colonna di output separata.

Ecco il risultato:

city_of_deliverytotal_number_of_packagesaverage_number_of_packages
Split531177.00
Izmir5,9361,978.67
Ankara9,1393,046.33
Gdansk712237.33
Rijeka627209.00
Zagreb930310.00
Istanbul13,8574,619.00
Krakow673224.33
Warsaw2,358786.00

Una query, due funzioni aggregate: L'approccio avanzato

La versione avanzata è quella in cui le aggregazioni "comunicano", cioè devono prima trovare un valore aggregato e poi usarlo per calcolare un altro valore aggregato. In genere, questo si ottiene con le subquery o con le Common Table Expressions (CTE).

L'esempio che segue mostra l'uso delle subquery. La nostra guida sulla combinazione di due funzioni aggregate in GROUP BY copre entrambi gli approcci.

Esempio

Il codice seguente restituisce il numero medio giornaliero di pacchi consegnati in ogni Paese:

SELECT country_of_delivery,
	 AVG(pd.daily_number_of_packages) AS average_daily_number_of_packages
FROM (SELECT date_of_delivery, 
	       country_of_delivery,
	 	 SUM(number_of_packages) AS daily_number_of_packages
	FROM package_deliveries
	GROUP BY date_of_delivery, country_of_delivery) AS pd
GROUP BY country_of_delivery;

Per prima cosa devo trovare il numero di pacchi consegnati giornalmente in ogni paese, che è la prima aggregazione. La seconda aggregazione utilizza questo risultato e calcola la media giornaliera per paese.

La prima aggregazione è scritta nella subquery. Utilizza la funzione SUM() ed elenca le colonne date_of_delivery e country_of_delivery in SELECT. L'output è raggruppato per le stesse colonne.

Ora posso scrivere la query principale, facendo riferimento in AVG() alla colonna daily_number_of_packages della subquery. Raggruppo l'output per paese e ottengo il numero medio giornaliero di pacchi consegnati per ogni paese.

country_of_deliveryaverage_daily_number_of_packages
Turkey9,644.00
Croatia696.00
Poland1,247.67

GROUP BY con aggregati condizionali

L'istruzione CASE o CASE WHEN etichetta i dati in base ai loro valori. Questa istruzione può essere utilizzata anche con GROUP BY.

Raggruppare i dati per aggregati condizionali significa usare CASE WHEN con GROUP BY. Tuttavia, e questo è importante, l'istruzione CASE WHEN scritta in SELECT deve comparire anche in GROUP BY.

Esempio

Utilizzando la tabella dell'esempio precedente, posso scrivere un codice che classifica i Paesi in UE e non UE e mostra il numero totale di pacchi consegnati per ogni categoria:

SELECT
  CASE 
   WHEN country_of_delivery = 'Turkey' THEN 'Non-EU'
   ELSE 'EU'
  END,
  SUM(number_of_packages) AS total_number_of_packages
FROM package_deliveries
GROUP BY CASE 
   WHEN country_of_delivery = 'Turkey' THEN 'Non-EU'
   ELSE 'EU'
  END;

L'istruzione CASE dice che la Turchia deve essere categorizzata come Paese non UE. Questa condizione è indicata in WHEN. La categoria per tutti gli altri Paesi è l'UE, scritta in ELSE.

L'istruzione CASE inizia con CASE (da cui il nome) e termina con la parola chiave END.

Uso la funzione SUM() per calcolare il numero totale di pacchetti. Per mostrare questo valore per categoria, ho semplicemente copiato l'intera istruzione CASE WHEN in GROUP BY.

Ecco l'output:

casetotal_number_of_packages
Non-EU28,932
EU5,831

Se avete bisogno di altri esempi per capire meglio, leggete una delle nostre guide:

Estensioni di GROUP BY: ROLLUP, CUBO, SET DI RAGGRUPPAMENTO

Le tre estensioni di SQL GROUP BY sono:

  • ROLLUP - Crea una riga di riepilogo per i gruppi elencati in GROUP BY.
  • CUBE - Crea subtotali per tutte le combinazioni dei gruppi elencati in GROUP BY.
  • GROUPING SETS - Aggrega l'output su più livelli.

Nell'esempio, viene mostrato il funzionamento di GROUPING SETS. Per sapere come funzionano le altre due estensioni, consultare la guida alle estensioni GROUP BY.

Esempio

Il codice seguente restituisce il numero di pacchi consegnati per paese e per data:

SELECT country_of_delivery,
	 date_of_delivery,
	 SUM(number_of_packages) AS total_number_of_packages
FROM package_deliveries
GROUP BY GROUPING SETS(country_of_delivery, date_of_delivery)
ORDER BY country_of_delivery, date_of_delivery;

Inizio usando SUM() per calcolare il numero di pacchi.

In GROUP BY, scrivo GROUPING SETS con tutti i livelli di aggregazione all'interno delle parentesi.

L'output mostra il numero di pacchi consegnati per paese e per data di consegna:

country_of_deliverydate_of_deliverytotal_number_of_packages
CroatiaNULL2,088
PolandNULL3,743
TurkeyNULL28,932
NULL2024-03-012,730
NULL2024-03-0211,208
NULL2024-03-0320,825

Può essere utile pensare ai set di raggruppamento come a due query separate. La prima query raggruppa per paese ...

SELECT country_of_delivery,
       NULL AS date_of_delivery,
       SUM(number_of_packages) AS total_number_of_packages
FROM package_deliveries
GROUP BY country_of_delivery
ORDER BY country_of_delivery;

... e restituisce le prime tre righe dell'output precedente:

country_of_deliverydate_of_deliverytotal_number_of_packages
CroatiaNULL2,088
PolandNULL3,743
TurkeyNULL28,932

La seconda query raggruppa per data di consegna ...

SELECT NULL AS country_of_delivery,
       date_of_delivery,
       SUM(number_of_packages) AS total_number_of_packages
FROM package_deliveries
GROUP BY date_of_delivery
ORDER BY date_of_delivery;

... e restituisce le altre tre righe del risultato originale:

country_of_deliverydate_of_deliverytotal_number_of_packages
NULL2024-03-012,730
NULL2024-03-0211,208
NULL2024-03-0320,825

In altre parole, se si uniscono queste due query di raggruppamento separate utilizzando UNION...

SELECT country_of_delivery,
       NULL AS date_of_delivery,
       SUM(number_of_packages) AS total_number_of_packages
FROM package_deliveries
GROUP BY country_of_delivery

UNION 

SELECT NULL AS country_of_delivery,
       date_of_delivery,
       SUM(number_of_packages) AS total_number_of_packages
FROM package_deliveries
GROUP BY date_of_delivery
ORDER BY country_of_delivery, date_of_delivery;

... si ottiene esattamente lo stesso risultato di GROUPING SETS.

country_of_deliverydate_of_deliverytotal_number_of_packages
CroatiaNULL2,088
PolandNULL3,743
TurkeyNULL28,932
NULL2024-03-012,730
NULL2024-03-0211,208
NULL2024-03-0320,825

Errori comuni nell'uso di GROUP BY

Confondere ORDER BY e GROUP BY

Spesso si tratta di non sapere cosa fa GROUP BY.

Lasciate che ve lo dimostri con un esempio.

Supponiamo di voler trovare il numero totale di pacchi per paese di consegna.

Se non si ha familiarità con GROUP BY, si potrebbe scrivere una soluzione ingenua usando ORDER BY.

SELECT date_of_delivery,
	 city_of_delivery,
	 country_of_delivery
FROM package_deliveries
ORDER BY country_of_delivery;

Ora che avete i dati ordinati per paese, come mostrato nell'istantanea qui sotto, decidete di sommare manualmente i valori per ottenere il risultato per paese.

date_of_deliverycity_of_deliverycountry_of_delivery
2024-03-01RijekaCroatia
2024-03-01SplitCroatia
2024-03-01ZagrebCroatia
2024-03-02RijekaCroatia
2024-03-02SplitCroatia
2024-03-02ZagrebCroatia
2024-03-03ZagrebCroatia
2024-03-03SplitCroatia
2024-03-03RijekaCroatia
2024-03-01KrakowPoland
2024-03-01WarsawPoland

Ma perché fare manualmente qualcosa che GROUP BY fa automaticamente? Invece di ordinare i dati per paese, si dovrebbe raggruppare per esso e usare SUM() per sommare i dati:

SELECT country_of_delivery,
	 SUM(number_of_packages) AS total_number_of_packages
FROM package_deliveries
GROUP BY country_of_delivery
ORDER BY country_of_delivery;

In questo modo si ottiene immediatamente il risultato desiderato:

country_of_deliverytotal_number_of_packages
Croatia2,088
Poland3,743
Turkey28,932

Per saperne di più sulle differenze tra GROUP BY e ORDER BY e su come utilizzare GROUP BY e ORDER BY insieme.

Confondere WHERE e HAVING

Un altro errore comune è cercare di filtrare i valori aggregati utilizzando WHERE. Questo non è possibile: WHERE viene utilizzato per filtrare le singole righe prima dell' aggregazione. Invece, HAVING serve a filtrare gruppi di righe dopo l' aggregazione.

Esempio

Se si vuole ottenere il numero medio di pacchi consegnati ogni giorno per città e mostrare solo quelli con più di 500 pacchi, si può decidere di scrivere questa query:

SELECT city_of_delivery,
	 AVG(number_of_packages) AS average_number_of_packages
FROM package_deliveries
WHERE AVG(number_of_packages) > 500
GROUP BY city_of_delivery;

La query restituirà un errore perché WHERE non accetta una funzione di aggregazione come argomento. (Questo non significa che non si possa mai usare WHERE con GROUP BY; si può, ma non per filtrare gruppi).

In questo caso, si deve usare HAVING:

SELECT city_of_delivery,
	 AVG(number_of_packages) AS average_number_of_packages
FROM package_deliveries
GROUP BY city_of_delivery
HAVING AVG(number_of_packages) > 500;

È la stessa query con AVG() e GROUP BY. L'unica differenza è HAVING, in cui si confronta il calcolo di AVG() con 500.

L'output mostra solo le città la cui media giornaliera è superiore a 500.

city_of_deliveryaverage_number_of_packages
Izmir1,978.67
Ankara3,046.33
Istanbul4,619.00
Warsaw786.00

Per saperne di più, consultare l'articolo HAVING vs WHERE.

Elencare colonne non aggregate in SELECT ma non in WHERE

La regola semplice da ricordare è che qualsiasi colonna non aggregata scritta in SELECT deve essere inclusa anche in GROUP BY. Se non si fa così, il database non saprà quale valore mostrare se diversi valori sono presenti nello stesso gruppo.

Esempio

Ad esempio, si scrive una query che deve calcolare il numero totale di pacchetti per paese e per città.

SELECT country_of_delivery,
       city_of_delivery,
	 SUM(number_of_packages) total_number_of_packages
FROM package_deliveries
GROUP BY country_of_delivery;

Certo, il Paese e la città sono inseriti in SELECT, ma si è dimenticato di inserire la città in GROUP BY. La query non verrà eseguita. Verrà restituito un errore. Anche se i messaggi sono formulati in modo diverso in PostgreSQL, Oracle e altri database, il messaggio è lo stesso: la colonna city_of_delivery deve apparire in GROUP BY.

Anche se funzionasse, il database sarebbe confuso. Penserebbe qualcosa del genere: "Volete mostrare le città ma non volete raggruppare per città? Come faccio a sapere quale città mostrare nell'output se ogni paese ne ha tre? Per favore, mettete le città in GROUP BY così posso mostrare ogni città come un gruppo separato".

Quindi, lo si aiuta includendo la città di consegna in GROUP BY:

SELECT country_of_delivery,
       city_of_delivery,
	 SUM(number_of_packages) total_number_of_packages
FROM package_deliveries
GROUP BY country_of_delivery, city_of_delivery;

Sì, si tratta di raggruppare per due colonne e avete già imparato a farlo. Ecco l'output della query:

country_of_deliverycity_of_deliverytotal_number_of_packages
CroatiaZagreb930
CroatiaRijeka627
CroatiaSplit531
TurkeyIstanbul13,857
PolandWarsaw2,358
PolandKrakow673
TurkeyAnkara9,139
PolandGdansk712
TurkeyIzmir5,936

Altri errori

Ci sono anche altri errori, come dimenticare GROUP BY con le funzioni aggregate o non raggruppare per una chiave unica. Questi e altri sono trattati in questo articolo sugli errori comuni di GROUP BY.

Ulteriori risorse SQL GROUP BY

Dopo aver letto questa panoramica sulla clausola SQL GROUP BY, dovreste avere un'idea dei suoi usi e delle sue difficoltà. Ma se si vuole padroneggiare la clausola GROUP BY, è necessario approfondire i dettagli.

Il modo migliore per farlo è consultare alcuni dei nostri corsi e libri di cucina. Ecco alcuni dei miei suggerimenti per approfondire la conoscenza:

  • Come creare semplici report SQL - Questo corso di livello intermedio si concentra sulle sfumature dell'uso di GROUP BY - raggruppamento per più colonne, uso di HAVING, combinazione di GROUP BY con CASE WHEN, differenza tra COUNT(*) e COUNT(id), ecc.
  • Pratica su SQL - I corsi di questa traccia hanno sezioni dedicate a diversi argomenti di SQL, tra cui molte esercitazioni su GROUP BY.

E non dimenticate i nostri articoli con esempi GROUP BY. Due dei miei preferiti sono Pratica su SQL: 10 esercizi pratici su GROUP BY con soluzioni dettagliate e le 9 migliori domande di intervista su SQL GROUP BY.

Inoltre, c'è un foglio informativo su SQL per l'analisi dei dati, che contiene una sezione dedicata a GROUP BY.

Buon apprendimento!