SQL - Group by Having
SQL - Group by Having
INDICE
Lo schema relazionale
Le tabelle di esempio
Le query richieste
Query 1: soluzione proposta
Query 2: soluzione proposta
Prima alternativa corretta
Seconda alternativa corretta
Terza alternativa corretta
Quarta alternativa corretta
Quinta alternativa corretta
Alternativa corretta solo in mancanza di hotel omonimi
Alternativa analoga alla seconda ma non ottimizzata
Alternativa analoga alla quarta ma non ottimizzata
Alternativa errata
Query 3: soluzione proposta
Prima alternativa corretta
Seconda alternativa corretta
Alternativa corretta solo in mancanza di hotel omonimi
Alternativa analoga alla seconda ma non ottimizzata
Alternativa incompleta
Alternativa errata
Query 4: soluzione proposta
Prima alternativa corretta
Seconda alternativa corretta
Alternativa corretta solo in mancanza di hotel omonimi
Alternativa analoga alla seconda ma non ottimizzata
Prima alternativa errata
Seconda alternativa errata
Query 5: soluzione proposta
Alternativa non ottimizzata
Alternativa errata
Query 6: soluzione proposta
Prima alternativa errata
Seconda alternativa errata
Terza alternativa errata
Quarta alternativa errata
Quinta alternativa errata
Query 7: soluzione proposta
Prima alternativa non ottimizzata
Seconda alternativa non ottimizzata
Query 8: soluzione proposta
Alternativa corretta solo in mancanza di hotel omonimi
Alternativa non ottimizzata
Prima alternativa errata
Seconda alternativa errata
1
Bocchi Cinzia 03/01/2015
LO SCHEMA RELAZIONALE
torna all’indice
2
Bocchi Cinzia 03/01/2015
LE TABELLE DI ESEMPIO
hotel
codHotel nome citta
100 Miramare Rimini
110 Marittimo Rimini
120 La baita Aosta
130 Miramare Napoli
140 Fiesta Rimini
150 Fiesta Torino
stanza
numStanza codHotel tipo prezzo occupata
1 100 singola 60,00 1
2 100 doppia 58,00 1
3 100 singola 65,00 0
4 100 doppia 61,00 1
1 110 singola 60,00 1
2 110 doppia 80,00 0
3 110 singola 95,00 0
1 120 singola 100,00 1
2 120 doppia 95,00 0
3 120 singola 150,00 0
4 120 singola 200,00 1
21 130 doppia 250,00 0
22 130 singola 300,00 0
25 130 singola 150,00 0
55 140 doppia 99,00 1
58 140 singola 100,00 1
1 150 doppia 250,00 0
2 150 singola 180,00 0
3 150 singola 150,00 0
4 150 doppia 250,00 1
5 150 singola 160,00 1
6 150 doppia 350,00 1
7 150 singola 100,00 1
3
Bocchi Cinzia 03/01/2015
cliente
idCliente nome città
1 Rossi Torino
2 Neri Milano
3 Verdi Roma
4 Rossi Catania
5 Verdi Roma
6 Bianchi Roma
7 Marrone Roma
prenotazione
numStanza codHotel idCliente data Inizio dataFine
1 100 2 2013-07-14 2013-07-20
1 100 4 2013-08-10 2013-08-20
2 110 1 2013-07-02 2013-07-09
55 140 3 2013-08-20 2013-08-28
3 100 4 2013-09-01 2013-09-18
55 140 5 2013-09-12 2013-09-30
58 140 6 2013-07-01 2013-07-15
4 120 7 2014-05-10 2014-05-20
22 130 1 2014-06-05 2014-06-15
4 150 3 2015-03-01
5 150 4 2015-03-15
1 120 2 2015-05-20
1 150 3 2015-07-12
2 150 5 2015-07-20
3 150 6 2015-07-15
1 100 7 2015-07-13
3 100 4 2015-07-19
3 110 2 2015-07-11
torna all’indice
4
Bocchi Cinzia 03/01/2015
LE QUERY RICHIESTE
torna all’indice
5
Bocchi Cinzia 03/01/2015
passo 1 Sulla tabella hotel viene effettuato un raggruppamento in base al campo citta.
passo 2 Viene eseguita la funzione count presente in select per ogni gruppo.
citta NumeroHotel
Rimini 3
Aosta 1
Napoli 1
Torino 1
torna all’indice
6
Bocchi Cinzia 03/01/2015
passo 1 Viene eseguito il prodotto cartesiano delle tabelle presenti in from: ogni riga
della tabella hotel viene combinata con tutte le righe della tabella stanza.
7
Bocchi Cinzia 03/01/2015
10
Bocchi Cinzia 03/01/2015
passo 4 Viene effettuato il raggruppamento sui campi codHotel e nome della tabella
hotel (vedere i nomi colonne evidenziati in giallo).
11
Bocchi Cinzia 03/01/2015
Come si può notare, il codice dell’hotel consente di distinguere tra hotel che hanno lo
stesso nome.
torna all’indice
In tal caso il resultset non presenta la colonna codHotel, ma gli hotel con lo stesso nome e
codice diverso non vengono raggruppati.
nome NumStanzeOccupate
Miramare 3
Marittimo 1
La baita 2
Fiesta 2
Fiesta 4
torna all’indice
12
Bocchi Cinzia 03/01/2015
passo 1 Viene applicata la condizione presente in where alla tabella stanza: tutte le
righe che non soddisfano la condizione S.occupata = 1 vengono eliminate.
13
Bocchi Cinzia 03/01/2015
codHotel NumStanzeOccupate
100 3
110 1
120 2
140 2
150 4
torna all’indice
14
Bocchi Cinzia 03/01/2015
passo 3 Viene effettuato il raggruppamento sui campi codHotel e nome della tabella
hotel (vedere i nomi colonne evidenziati in giallo).
15
Bocchi Cinzia 03/01/2015
In questo caso il resultset ci fornisce un’informazione in più: l’hotel Miramare di codice 130
ha 0 stanze occupate.
torna all’indice
16
Bocchi Cinzia 03/01/2015
Se non interessa il nome dell’Hotel, la terza alternativa può essere ricondotta a questo
caso.
passo 1 Viene effettuato il raggruppamento sul campo codHotel della tabella stanza
17
Bocchi Cinzia 03/01/2015
codHotel NumStanzeOccupate
100 3
110 1
120 2
130 0
140 2
150 4
torna all’indice
18
Bocchi Cinzia 03/01/2015
Questa soluzione è simile alla terza alternativa, con la differenza che il campo codHotel
non compare nel resultset ma viene utilizzato per distinguere tra eventuali hotel omonimi.
nome NumStanzeOccupate
Miramare 3
Marittimo 1
La baita 2
Miramare 0
Fiesta 2
Fiesta 4
torna all’indice
I passi da 1 a 3 sono identici al caso principale mostrato, ma dal passo 4 si verificano dei
cambiamenti; vediamo quali.
passo 4 Viene effettuato il raggruppamento sul campo nome della tabella hotel
(vedere i nomi colonne evidenziati in giallo).
19
Bocchi Cinzia 03/01/2015
nome NumStanzeOccupate
Miramare 3
Marittimo 1
La baita 2
Fiesta 6
torna all’indice
20
Bocchi Cinzia 03/01/2015
codHotel NumStanzeOccupate
100 3
110 1
120 2
140 2
150 4
Il resultset fornisce le informazioni richieste, tuttavia viene effettuato del lavoro superfluo
per il prodotto cartesiano delle tabelle e l’equi-join. Se non serve il nome dell’hotel, è
sufficiente utilizzare la tabella stanza. Si veda la seconda alternativa corretta.
torna all’indice
Il resultset fornisce le informazioni richieste, tuttavia viene effettuato del lavoro superfluo
per il prodotto cartesiano delle tabelle e l’equi-join. Se non serve il nome dell’hotel, è
sufficiente utilizzare la tabella stanza. Si veda la quarta alternativa corretta.
codHotel NumStanzeOccupate
100 3
110 1
120 2
130 0
140 2
150 4
torna all’indice
21
Bocchi Cinzia 03/01/2015
Alternativa errata
SELECT H.nome
FROM hotel H, stanza S
WHERE H.codHotel = S.codHotel AND S.occupata = 1
GROUP BY H.nome
I passi da 1 a 3 sono identici al caso principale mostrato, ma dal passo 4 si verificano dei
cambiamenti; vediamo quali.
passo 4 Viene effettuato il raggruppamento sul campo nome della tabella hotel
(vedere i nomi colonne evidenziati in giallo).
nome
Miramare
Marittimo
La baita
Fiesta
torna all’indice
22
Bocchi Cinzia 03/01/2015
passo 1 Viene eseguito il prodotto cartesiano delle tabelle presenti in from: ogni riga
della tabella hotel viene combinata con tutte le righe della tabella stanza.
passo 3 Viene effettuato il raggruppamento sui campi codHotel e nome della tabella
hotel (vedere i nomi colonne evidenziati in giallo).
26
Bocchi Cinzia 03/01/2015
passo 4 Vengono eseguite le funzioni MIN e MAX presenti nella select, per ciascun
gruppo.
torna all’indice
Come si può notare, non è presente la colonna codHotel, ma gli hotel che hanno lo stesso
nome vengono mantenuti distinti.
torna all’indice
28
Bocchi Cinzia 03/01/2015
passo 1 Viene effettuato il raggruppamento sul campo codHotel della tabella stanza
passo 2 Vengono eseguite le funzioni MIN e MAX presenti nella select, per ciascun
gruppo.
29
Bocchi Cinzia 03/01/2015
torna all’indice
30
Bocchi Cinzia 03/01/2015
passo 3 Viene effettuato il raggruppamento sul campo nome della tabella hotel
(vedere i nomi colonne evidenziati in giallo).
passo 4 Vengono eseguite le funzioni MIN e MAX presenti nella select, per ciascun
gruppo.
31
Bocchi Cinzia 03/01/2015
torna all’indice
32
Bocchi Cinzia 03/01/2015
Il resultset fornisce le informazioni richieste, tuttavia viene effettuato del lavoro superfluo
per il prodotto cartesiano delle tabelle e l’equi-join. Se non serve il nome dell’hotel, è
sufficiente utilizzare la tabella stanza. Si veda la seconda alternativa corretta.
torna all’indice
Alternativa incompleta
I passi sono da 1 a 3 sono identici alla soluzione principale. Al passo 4 non viene
effettuato il calcolo del minimo e, di conseguenza, il resultset è incompleto poiché non
contiene il prezzo minimo.
torna all’indice
33
Bocchi Cinzia 03/01/2015
Alternativa errata
torna all’indice
34
Bocchi Cinzia 03/01/2015
4) Per ogni hotel trovare il prezzo minimo e massimo delle stanze singole
passo 1 Viene eseguito il prodotto cartesiano delle tabelle presenti in from: ogni riga
della tabella hotel viene combinata con tutte le righe della tabella stanza.
38
Bocchi Cinzia 03/01/2015
passo 4 Viene effettuato il raggruppamento sui campi codHotel e nome della tabella
hotel (vedere i nomi colonne evidenziati in giallo).
passo 5 Vengono eseguite le funzioni MIN e MAX presenti nella select, per ciascun
gruppo.
39
Bocchi Cinzia 03/01/2015
140 Fiesta ... ... 100,00 ... gruppo 5: 140 Fiesta min=100 max=100
torna all’indice
40
Bocchi Cinzia 03/01/2015
torna all’indice
passo 2 Viene effettuato il raggruppamento sul campo codHotel della tabella stanza
passo 3 Vengono eseguite le funzioni MIN e MAX presenti nella select, per ciascun
gruppo.
42
Bocchi Cinzia 03/01/2015
torna all’indice
passo 4 Viene effettuato il raggruppamento sul campo nome della tabella hotel
(vedere i nomi colonne evidenziati in giallo).
passo 5 Vengono eseguite le funzioni MIN e MAX presenti nella select, per ciascun
gruppo.
43
Bocchi Cinzia 03/01/2015
torna all’indice
Il resultset fornisce le informazioni richieste, tuttavia viene effettuato del lavoro superfluo
per il prodotto cartesiano delle tabelle e l’equi-join. Se non serve il nome dell’hotel, è
sufficiente utilizzare la tabella stanza. Si veda la seconda alternativa corretta.
44
Bocchi Cinzia 03/01/2015
torna all’indice
Mancano l’equi join e la condizione che seleziona solo le stanze singole. Si lavora,
pertanto, sulla tabella derivata dal prodotto cartesiano delle tabelle in from, con record tra
loro non correlati. Il resultset ottenuto è errato.
torna all’indice
45
Bocchi Cinzia 03/01/2015
46
Bocchi Cinzia 03/01/2015
I valori di MIN e MAX sono errati perché comprendono stanze di tipologia diversa dalla
singola.
torna all’indice
47
Bocchi Cinzia 03/01/2015
50
Bocchi Cinzia 03/01/2015
passo 3 Viene applicata la condizione where H.citta = ‘Rimini’: tutte gli hotel che non
sono di Rimini vengono eliminati.
51
Bocchi Cinzia 03/01/2015
idCliente NumeroPrenotazioni
4 2
1 1
3 1
5 1
6 1
torna all’indice
52
Bocchi Cinzia 03/01/2015
torna all’indice
Alternativa errata
SELECT P.idCliente
FROM prenotazione P, hotel H
WHERE P.codHotel = H.codHotel AND H.citta = ‘Rimini’ AND P.datainizio
BETWEEN ‘2013-01-01’ AND ‘2013-12-31’
GROUP BY P.idCliente
idCliente
4
1
3
5
6
torna all’indice
53
Bocchi Cinzia 03/01/2015
passo 1 Viene effettuato il raggruppamento sul campo tipo della tabella stanza.
passo 3 Viene eseguita la funzione COUNT presente in having, per ciascun gruppo.
passo 4 Viene applicata la condizione in having COUNT(*) > 100, a ciascun gruppo.
Nessuno dei due gruppi ha un valore di count superiore a 100 perché , per evidenti motivi,
le tabelle di esempio fornite hanno un numero limitato di record. Quindi, per ciò che
rifuarda l’esempio, il result set sarebbe vuoto. Tuttavia, per comprendere il significato della
55
Bocchi Cinzia 03/01/2015
clausola having, supponiamo che la condizione sia COUNT(*) >9. Solo il gruppo 1
soddisfa la condizione e il gruppo 2 viene escluso.
tipo PrezzoMedio
singola 133,57
torna all’indice
passo 4 Viene applicata la condizione in having S.tipo > 100, a ciascun gruppo.
Tuttavia l’attributo tipo non è relativo a un gruppo ma a ogni singolo record della tabella e,
di conseguenza la condizione non può essere valutata. La query restituisce un errore.
torna all’indice
56
Bocchi Cinzia 03/01/2015
passo 1 Viene effettuato il raggruppamento sui campi tipo e codHotel della tabella
stanza.
passo 4 Viene applicata la condizione presente in having NumStanze > 100, cioè
COUNT(*)>100, a ciascun gruppo. Nessun gruppo soddisfa la condizione, ma
supponiamo che essa sia NumStanze > 2. Tutti i gruppi che non soddisfano tale
condizione vengono eliminati.
58
Bocchi Cinzia 03/01/2015
La query non genera errori ma il risultato ottenuto è ben diverso da quello richiesto.
torna all’indice
59
Bocchi Cinzia 03/01/2015
passo 1 Viene eseguito il raggruppamento sul campo numStanza della tabella stanza.
60
Bocchi Cinzia 03/01/2015
passo 4 Viene applicata la condizione presente in having NumStanze > 100, cioè
COUNT(*)>100, a ciascun gruppo. Nessun gruppo soddisfa la condizione, ma
supponiamo che essa sia NumStanze > 2. Tutti i gruppi che non soddisfano tale
condizione vengono eliminati.
62
Bocchi Cinzia 03/01/2015
La query non genera errori ma il risultato ottenuto è ben diverso da quello richiesto.
torna all’indice
passo 4 Viene applicata la condizione in having numStanza > 100, a ciascun gruppo.
Tuttavia l’attributo tipo non è relativo a un gruppo ma a ogni singolo record della tabella e,
di conseguenza la condizione non può essere valutata. La query restituisce un errore.
torna all’indice
63
Bocchi Cinzia 03/01/2015
PrezzoMedio COUNT(S.tipo)
133,57 14
165,89 9
La query non genera errori, ma i risultati ottenuti non sono interpretabili perché non si sa a
che cosa si riferiscono i dati contenuti nelle due colonne.
torna all’indice
64
Bocchi Cinzia 03/01/2015
passo 1 Viene applicata la condizione where dataInizio < ‘2015-07-10’ alla tabella
prenotazione.
65
Bocchi Cinzia 03/01/2015
passo 4 Viene applicata la condizione having NumeroPrenotazioni > 10: tutti i gruppi
il cui valore di count è minore o uguale a 10 vengono eliminati. Per ragioni già speigate in
precedenza, supponiamo che la condizione in having sia NumeroPrenotazioni > 1.
codHotel NumeroPrenotazioni
100 3
120 2
140 3
150 2
torna all’indice
66
Bocchi Cinzia 03/01/2015
Il risultato è lo stesso della soluzione principale, con un carico di lavoro aggiuntivo dovuto
al prodotto cartesiano delle due tabelle e alla condizione di equi join.
codHotel NumeroPrenotazioni
100 3
120 2
140 3
150 2
torna all’indice
Il risultato è lo stesso della soluzione principale, con un carico di lavoro aggiuntivo dovuto
al prodotto cartesiano delle due tabelle e alla condizione di equi join.
codHotel NumeroPrenotazioni
100 3
120 2
140 3
150 2
torna all’indice
67
Bocchi Cinzia 03/01/2015
8) Per ogni città e per ogni hotel operante in tale città determinare il numero di
prenotazioni effettuate nel periodo 10-07-2015 e 20-07-2015 (si utilizzi dataInizio)
da clienti provenienti da Roma
passo 1 Viene eseguito il prodotto cartesiano tra le tre tabelle presenti in from. Vista la
quantità di dati, passerò subito a mostrare i risultati ottenuti al passo 2.
... cod idC data Inizio ... cod nome citta idC ... città
Hote lien Hote lien
l te l te
... 100 2 2013-07-14 ... 100 Miramare Rimini 2 ... Milano
... 100 4 2013-08-10 ... 100 Miramare Rimini 4 ... Catania
... 110 1 2013-07-02 ... 110 Marittimo Rimini 1 ... Torino
... 140 3 2013-08-20 ... 140 Fiesta Rimini 3 ... Roma
... 100 4 2013-09-01 ... 100 Miramare Rimini 4 ... Catania
... 140 5 2013-09-12 ... 140 Fiesta Rimini 5 ... Roma
... 140 6 2013-07-01 ... 140 Fiesta Rimini 6 ... Roma
... 120 7 2014-05-10 ... 120 La baita Aosta 7 ... Roma
... 130 1 2014-06-05 ... 130 Miramare Napoli 1 ... Torino
... 150 3 2015-03-01 ... 150 Fiesta Torino 3 ... Roma
... 150 4 2015-03-15 ... 150 Fiesta Torino 4 ... Catania
... 120 2 2015-05-20 ... 120 La baita Aosta 2 ... Milano
... 150 3 2015-07-12 ... 150 Fiesta Torino 3 ... Roma
... 150 5 2015-07-20 ... 150 Fiesta Torino 5 ... Roma
... 150 6 2015-07-15 ... 150 Fiesta Torino 6 ... Roma
... 100 7 2015-07-13 ... 100 Miramare Rimini 7 ... Roma
... 100 4 2015-07-19 ... 100 Miramare Rimini 4 ... Catania
... 110 2 2015-07-11 ... 110 Marittimo Rimini 2 ... Milano
... cod idC data Inizio ... cod nome citta idC ... città
Hote lien Hote lien
l te l te
... 150 3 2015-07-12 ... 150 Fiesta Torino 3 ... Roma
... 150 5 2015-07-20 ... 150 Fiesta Torino 5 ... Roma
... 150 6 2015-07-15 ... 150 Fiesta Torino 6 ... Roma
... 100 7 2015-07-13 ... 100 Miramare Rimini 7 ... Roma
... 100 4 2015-07-19 ... 100 Miramare Rimini 4 ... Catania
... 110 2 2015-07-11 ... 110 Marittimo Rimini 2 ... Milano
68
Bocchi Cinzia 03/01/2015
... cod idC data Inizio ... cod nome citta idC ... città
Hote lien Hote lien
l te l te
... 150 3 2015-07-12 ... 150 Fiesta Torino 3 ... Roma
... 150 5 2015-07-20 ... 150 Fiesta Torino 5 ... Roma
... 150 6 2015-07-15 ... 150 Fiesta Torino 6 ... Roma
... 100 7 2015-07-13 ... 100 Miramare Rimini 7 ... Roma
passo 5 Viene eseguito il raggruppamento sui campi citta e codHotel della tabella
hotel.
torna all’indice
69
Bocchi Cinzia 03/01/2015
Alternativa corretta solo se non esistono hotel omonimi nella stessa città
Il resultset è uguale a quello restituito dalla soluzione principale, ma solo se non esistono
nella stessa città hotel con lo stesso nome.
torna all’indice
Il resultset è lo stesso che si ottiene con la soluzione principale, ma il lavoro svolto dal
sistema è più oneroso perché in from è stata inserita la tabella superflua stanza.
torna all’indice
Questa soluzione restituisce il numero di prenotazioni per ogni città e non distingue tra
prenotazioni fatti in hotel diversi della stessa città. La query viene eseguita ma restituisce
risultati diversi da quelli attesi.
torna all’indice
70
Bocchi Cinzia 03/01/2015
La query restituisce un errore perché il campo H.codHotel presente in select non è stato
riportato nella clausola group by.
torna all’indice
Quest'opera è stata rilasciata con licenza Creative Commons Attribuzione - Non commerciale - Condividi allo
stesso modo 3.0 Italia. Per leggere una copia della licenza visita il sito web
http://creativecommons.org/licenses/by-nc-sa/3.0/it/ o spedisci una lettera a Creative Commons, 171 Second
Street, Suite 300, San Francisco, California, 94105, USA.
71