Sei sulla pagina 1di 6

SQL: Raggruppamenti e clausola GROUP BY La clausola GROUP BY

Per introdurre i raggruppamenti, consideriamo la seguente tabella:


DIPENDENTI

matr 101 102 103 104 105 106

cognome Rossi Bianchi Verdi Neri Gialli Rosi

ruolo direttore impiegato impiegato direttore impiegato impiegato

stipendio 100 50 45 90 60 65

anzianit senior senior junior junior senior senior

Supponiamo di voler determinare la media e la somma degli stipendi dei dipendenti suddividendoli per in base al ruolo. Ci che vogliamo ottenere, in sostanza, un resultset come il seguente:
ruolo direttore impiegato media 95 55 somma 190 220

Per suddividere in gruppi le righe estratte occorre utilizzare la clausola GROUP BY, come mostrato nel seguente esempio: SELECT FROM GROUP BY ruolo, AVG (stipendio) AS media, SUM (stipendio) AS somma dipendenti ruolo

Cerchiamo di capire meglio come avviene lesecuzione del comando. Per prima cosa, vengono selezionate le righe che soddisfano le condizioni presenti in WHERE. In questo esempio vengono selezionate tutte le righe, non essendo presente la clausola WHERE. Successivamente, vengono raggruppate le varie righe in base ai campi specificati con la clausola GROUP BY. In questo caso vengono raggruppate le righe che hanno lo stesso valore nel campo ruolo. Infine, la clausola SELECT viene applicata a ciascun gruppo. Nellesempio vengono calcolate la media e la somma per ciascun gruppo. La tabella risultante conterr tante righe quanti sono i gruppi individuati e tante colonne quanti sono gli attributi e le funzioni di aggregazione definiti in SELECT.

Il procedimento rappresentato nella figura seguente.


Bocchi Cinzia Ultimo aggiornamento: 05/12/2012

DIPENDENTI

matr 102 103 105 106 101 104

cognome Bianchi Verdi Gialli Rosi Rossi Neri

ruolo impiegato impiegato impiegato impiegato direttore direttore

stipendio 50 45 60 65 100 90

anzianit senior junior senior gruppo impiegati: media=55 somma=220

senior
senior junior gruppo direttori: media=95 somma=190

Osservazione importante Gli attributi presenti in SELECT devono essere presenti anche nella clausola GROUP BY. Non vale il viceversa: in GROUP BY possono essere specificati attributi che non compaiono in SELECT. Il motivo di questa restrizione pu essere mostrato con un esempio. Supponiamo di voler eseguire la query seguente: SELECT FROM GROUP BY ruolo, anzianit, AVG (stipendio) AS media, SUM (stipendio) AS somma dipendenti ruolo

Lattributo anzianit presente in SELECT ma non in GROUP BY. Osservando la tabella ottenuta in precedenza si pu notare che per ciascun gruppo esistono valori diversi del campo anzianit e questo fatto rende impossibile rappresentare un solo valore nella tabella risultante
ruolo direttore impiegato anzianit ? ? media 95 55 somma 190 220

senior o junior? Volendo rappresentare anche lanzianit, dobbiamo aggiungere lattributo alla clausola GROUP BY. SELECT FROM GROUP BY ruolo, anzianit, AVG (stipendio) AS media, SUM (stipendio) AS somma dipendenti ruolo, anzianit

Bocchi Cinzia Ultimo aggiornamento: 05/12/2012

DIPENDENTI

matr 102 105 106 103 101 104

cognome Bianchi Gialli Rosi Verdi Rossi Neri

ruolo impiegato impiegato impiegato impiegato direttore direttore

stipendio 50 60 65 45 100 90

anzianit senior senior

impiegati senior: media=58 somma=175 impiegati junior: media=45 somma=45 direttori senior: media=100 somma=100 direttori junior: media=90 somma=90

senior
junior senior junior

I gruppi creati sono 4 e per ciascuno di essi vengono calcolate media e somma. Il resultset sar:
ruolo direttore direttore impiegato impiegato anzianit senior junior senior junior media 100 90 58 45 somma 100 90 175 45

Nel caso in cui non ci interessi mostrare lanzianit nel resultset, potremo omettere lattributo da SELECT, senza per eliminarlo da GROUP BY: SELECT FROM GROUP BY
ruolo direttore direttore impiegato impiegato

ruolo, AVG (stipendio) AS media, SUM (stipendio) AS somma dipendenti ruolo, anzianit
media 100 90 58 45 somma 100 90 175 45

Come ulteriore esempio, supponiamo di voler calcolare il numero di dipendenti raggruppandoli in base al ruolo e allanzianit di servizio. SELECT FROM GROUP BY ruolo, anzianit, COUNT (*) AS numDipendenti dipendenti ruolo, anzianit
3

Bocchi Cinzia Ultimo aggiornamento: 05/12/2012

DIPENDENTI

matr 102 105 106 103 101 104

cognome Bianchi Gialli Rosi Verdi Rossi Neri

ruolo impiegato impiegato impiegato impiegato direttore direttore

stipendio 50 60 65 45 100 90

anzianit senior senior

impiegati senior: count=3

senior
junior senior junior

impiegati junior: count=1

direttori senior: count=1 direttori junior: count=1

Sui gruppi ottenuti viene eseguita la funzione COUNT e si ottiene il seguente risultato:
ruolo direttore direttore impiegato impiegato anzianit senior junior senior junior numDipendenti 1 1 3 1

Se si vuole ottenere un analogo risultato, ma solo per gli impiegati, si pu aggiungere la clausola WHERE, come nellesempio seguente. SELECT FROM WHERE GROUP BY anzianit, COUNT (*) AS numImpiegati dipendenti ruolo = impiegato anzianit;

Prima di raggruppare i risultati vengono eliminate le righe che nel campo ruolo hanno valori diversi da impiegato.
DIPENDENTI

matr 102 105 106 103

cognome Bianchi Gialli Rosi Verdi

ruolo impiegato impiegato impiegato impiegato

stipendio 50 60 65 45

anzianit senior senior impiegati senior: count=3 impiegati junior: count=1

senior
junior

Bocchi Cinzia Ultimo aggiornamento: 05/12/2012

Resultset:
anzianit senior junior numImpiegati 3 1

La clausola HAVING
La struttura del comando SELECT con raggruppamenti pu essere ulteriormente ampliata con la clausola HAVING con la quale possibile sottoporre al controllo di una o pi condizioni i gruppi creati con GROUP BY. La condizione scritta dopo HAVING normalmente controlla il valore restituito dalle funzioni di aggregazione. La clausola HAVING non deve essere confusa con la clausola WHERE. Questultima effettua selezioni sulle righe di una tabella, prima di qualsiasi raggruppamento. HAVING, invece, opera selezioni sui gruppi di righe ottenuti dopo i raggruppamenti. Nel caso dellesempio visto in precedenza SELECT FROM GROUP BY ruolo, anzianit, COUNT (*) AS numDipendenti dipendenti ruolo, anzianit;

si potrebbe voler ottenere in output solo i raggruppamenti per i quali il numero di dipendenti superiore a 1. In tal caso occorre scrivere: SELECT FROM GROUP BY HAVING oppure SELECT FROM GROUP BY HAVING ruolo, anzianit, COUNT (*) AS numDipendenti dipendenti ruolo, anzianit numDipendenti > 1; ruolo, anzianit, COUNT (*) AS numDipendenti dipendenti ruolo, anzianit COUNT (*) > 1;

Dopo aver effettuato il raggruppamento e prima di applicare la clausola SELECT, viene imposta la condizione in HAVING su ciascun gruppo. I gruppi che non soddisfano tale condizione non compariranno nella tabella risultante.

Bocchi Cinzia Ultimo aggiornamento: 05/12/2012

DIPENDENTI

matr 102 105 106 103 101 104

cognome Bianchi Gialli Rosi Verdi Rossi Neri

ruolo impiegato impiegato impiegato impiegato direttore direttore

stipendio 50 60 65 45 100 90

anzianit senior senior

impiegati senior: count=3

senior
junior senior junior

impiegati junior: count=1

direttori senior: count=1 direttori junior: count=1

Lunico gruppo che soddisfa la condizione in HAVING quello degli impiegati senior. Resultset:
ruolo impiegato anzianit senior numDipendenti 3

Quest'opera stata rilasciata con licenza Creative Commons Attribution-ShareAlike 3.0 Unported. Per leggere una copia della licenza visita il sito web http://creativecommons.org/licenses/by-sa/3.0/ o spedisci una lettera a Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA. 6

Bocchi Cinzia Ultimo aggiornamento: 05/12/2012