Capitolo 4


Le clausole SQL

Questo capitolo è dedicato alle clausole utilizzate con l’istruzione SELECT , in particolare saranno trattate le seguenti clausole:

Negli esempi di questo capitolo, quando non verrà specificato diversamente, si utilizzerà la seguente tabella:

ASSEGNI

ASSEGNO
-------------------

BENEFICIARIO
---------------------------------------
IMPORTO
-------------------
NOTE
---------------------------------------
1 COMPUTER SHOP
50 000
DISCHETTI E CD-ROM
2 LIBRERIE CULTURA
245 000
LIBRI, CANCELLERIA
3 COMPUTER SHOP
200 000
TELEFONO CELLULARE
4 BIOGAS SRL
88 000
GAS
5 SUPERMARCHET GS
150 000
ALIMENTARI
16 ASSICURAZIONI ASSO
425 000
ASSICURAZIONE CASA
17 GAS S.P.A.
25 000
GAS
21 COMPUTER SHOP
34 000
CONTROLLER
20 ABITI BELLA
110 000
PANTALONI
9 ABITI BELLA
224 000
COMPLETO DONNA
8 COMPUTER SHOP
134 000
JOYSTICK

WHERE

La clausola WHERE serve per implementare delle condizioni verificabili a livello delle singole righe.
Questa clausola è abbastanza semplice da usare ed è già stata utilizzata precedentemente in questo corso, vediamo un esempio:

SELECT * FROM ASSEGNI
WHERE IMPORTO < 150000;

ASSEGNO
-------------------

BENEFICIARIO
---------------------------------------
IMPORTO
-------------------
NOTE
---------------------------------------
1 COMPUTER SHOP
50 000
DISCHETTI E CD-ROM
4 BIOGAS SRL
88 000
GAS
17 GAS S.P.A.
25 000
GAS
21 COMPUTER SHOP
34 000
CONTROLLER
20 ABITI BELLA
110 000
PANTALONI
8 COMPUTER SHOP
134 000
JOYSTICK

Come possiamo vedere dall’esempio la condizione ‘IMPORTO < 150000’, implementata tramite la clausola WHERE, è stata posta a tutte le righe della tabella e solo per quelle righe dove tale condizione è risultata soddisfatta che sono stati estrapolati e visualizzati i dati secondo gli argomenti dell’istruzione SELECT.

ORDER BY

A volte potrebbe essere necessario presentare i risultati di una query in un certo ordine, la clausola ORDER BY assolve a questo scopo. Vediamo alcuni esempi:

SELECT *
FROM ASSEGNI
ORDER BY BENEFICIARIO;

ASSEGNO
-------------------

BENEFICIARIO
---------------------------------------
IMPORTO
-------------------
NOTE
---------------------------------------
20 ABITI BELLA
110 000
PANTALONI
9 ABITI BELLA
224 000
COMPLETO DONNA
16 ASSICURAZIONI ASSO
425 000
ASSICURAZIONE CASA
4 BIOGAS SRL
88 000
GAS
1 COMPUTER SHOP
50 000
DISCHETTI E CD-ROM
3 COMPUTER SHOP
200 000
TELEFONO CELLULARE
8 COMPUTER SHOP
134 000
JOYSTICK
21 COMPUTER SHOP
34 000
CONTROLLER
17 GAS S.P.A.
25 000
GAS
2 LIBRERIE CULTURA
245 000
LIBRI, CANCELLERIA
5 SUPERMARCHET GS
150 000
ALIMENTARI

E’ possibile ordinare i record in senso inverso, con la lettera o il numero più alti in prima posizione? Si che è possibile, tramite la parola chiave DESC. Vediamo un esempio:

SELECT *
FROM ASSEGNI
ORDER BY BENEFICIARIO DESC;

ASSEGNO
-------------------

BENEFICIARIO
---------------------------------------
IMPORTO
-------------------
NOTE
---------------------------------------
5 SUPERMARCHET GS
150 000
ALIMENTARI
2 LIBRERIE CULTURA
245 000
LIBRI, CANCELLERIA
17 GAS S.P.A.
25 000
GAS
1 COMPUTER SHOP
50 000
DISCHETTI E CD-ROM
21 COMPUTER SHOP
34 000
CONTROLLER
3 COMPUTER SHOP
200 000
TELEFONO CELLULARE
8 COMPUTER SHOP
134 000
JOYSTICK
4 BIOGAS SRL
88 000
GAS
16 ASSICURAZIONI ASSO
425 000
ASSICURAZIONE CASA
20 ABITI BELLA
110 000
PANTALONI
9 ABITI BELLA
224 000
COMPLETO DONNA

Esiste anche la parola chiave facoltativa ASC per l’ordinamento ascendente. Comunque questa parola chiave è raramente utilizzata in quanto superflua. Infatti ORDER BY, se non viene specificato diversamente, ordina per l’appunto in modo ascendente.

La clausola ORDER BY può essere applicata a più campi. Vediamo alcuni esempi:

SELECT BENEFICIARIO, NOTE
FROM ASSEGNI
ORDER BY BENEFICIARIO, NOTE;

BENEFICIARIO
---------------------------------------
NOTE
-------------
ABITI BELLA COMPLETO DONNA
ABITI BELLA PANTALONI
ASSICURAZIONI ASSO ASSICURAZIONE CASA
BIOGAS SRL GAS
COMPUTER SHOP CONTROLLER
COMPUTER SHOP DISCHETTI E CD-ROM
COMPUTER SHOP JOYSTICK
COMPUTER SHOP TELEFONO CELLULARE
GAS S.P.A. GAS
LIBRERIE CULTURA LIBRI, CANCELLERIA
SUPERMARCHET GS ALIMENTARI

SELECT BENEFICIARIO, NOTE
FROM ASSEGNI
ORDER BY BENEFICIARIO, NOTE DESC;

BENEFICIARIO
---------------------------------------
NOTE
----------------------
ABITI BELLA PANTALONI
ABITI BELLA COMPLETO DONNA
ASSICURAZIONI ASSO ASSICURAZIONE CASA
BIOGAS SRL GAS
COMPUTER SHOP TELEFONO CELLULARE
COMPUTER SHOP JOYSTICK
COMPUTER SHOP DISCHETTI E CD-ROM
COMPUTER SHOP CONTROLLER
GAS S.P.A. GAS
LIBRERIE CULTURA LIBRI, CANCELLERIA
SUPERMARCHET GS ALIMENTARI

Possiamo far riferimento ai campi da ordinare dopo ORDER BY indicando invece del loro nome il valore dell’ordine di apparizione all’interno della tabella. Vediamo un esempio:

SELECT *
FROM ASSEGNI
ORDER BY 3;

ASSEGNO
-------------------

BENEFICIARIO
---------------------------------------
IMPORTO
-------------------
NOTE
---------------------------------------
17 GAS S.P.A.
25 000
GAS
21 COMPUTER SHOP
34 000
CONTROLLER
1 COMPUTER SHOP
50 000
DISCHETTI E CD-ROM
4 BIOGAS SRL
88 000
GAS
20 ABITI BELLA
110 000
PANTALONI
8 COMPUTER SHOP
134 000
JOYSTICK
5 SUPERMARCHET GS
150 000
ALIMENTARI
3 COMPUTER SHOP
200 000
TELEFONO CELLULARE
9 ABITI BELLA
224 000
COMPLETO DONNA
2 LIBRERIE CULTURA
245 000
LIBRI, CANCELLERIA
16 ASSICURAZIONI ASSO
425 000
ASSICURAZIONE CASA

I dati sono stati visualizzati ordinandoli per il campo IMPORTO che è appunto il terzo campo che appare nella tabella ASSEGNI.

GROUP BY

Questa clausola ci permette di formare dei sottoinsiemi per quelle colonne specificate. Vediamo cosa significa quanto affermato.

SELECT BENEFICIARIO
FROM ASSEGNI
GROUP BY BENEFICIARIO;

BENEFICIARIO
---------------------------------------
ABITI BELLA
ASSICURAZIONI ASSO
BIOGAS SRL
COMPUTER SHOP
GAS S.P.A.
LIBRERIE CULTURA
SUPERMARCHET GS

Il risultato della query è una lista di beneficiari, che appaiono però una sola volta, anche se nella tabella di origine la maggior parte di essi compare più volte.

Questa clausola è usata molto spesso per applicare le funzioni di gruppo non a tutte le righe indistintamente, ma a sottoinsiemi di esse. Vediamo un esempio:

Vogliamo sapere quanto è stato elargito, in totale, per ogni beneficiario:

SELECT BENEFICIARIO, SUM(IMPORTO)
FROM ASSEGNI
GROUP BY BENEFICIARIO;

BENEFICIARIO
---------------------------------------
SUM(IMPORTO)
---------------------------
ABITI BELLA
334 000
ASSICURAZIONI ASSO
425 000
BIOGAS SRL
88 000
COMPUTER SHOP
418 000
GAS S.P.A.
25 000
LIBRERIE CULTURA
245 000
SUPERMARCHET GS
150 000

In questa query viene applicata la funzione di gruppo SUM per ogni sottoinsieme di BENEFICIARIO.

Da questo punto in poi dovremo considerare che alla tabella ASSEGNI sono stati aggiunti i seguenti record:

22
ABITI BELLA
79 000
PANTALONI
23 BIOGAS SRL
399 000
GAS
24 LIBRERIE CULTURA
224 000
LIBRI, CANCELLERIA
25 COMPUTER SHOP
88 000
CONTROLLER

Quindi la tabella così modificata apparirà nel seguente modo:

ASSEGNI

ASSEGNO
-------------------

BENEFICIARIO
---------------------------------------
IMPORTO
-------------------
NOTE
---------------------------------------
1 COMPUTER SHOP
50 000
DISCHETTI E CD-ROM
2 LIBRERIE CULTURA
245 000
LIBRI, CANCELLERIA
3 COMPUTER SHOP
200 000
TELEFONO CELLULARE
4 BIOGAS SRL
88 000
GAS
5 SUPERMARCHET GS
150 000
ALIMENTARI
16 ASSICURAZIONI ASSO
425 000
ASSICURAZIONE CASA
17 GAS S.P.A.
25 000
GAS
21 COMPUTER SHOP
34 000
CONTROLLER
20 ABITI BELLA
110 000
PANTALONI
9 ABITI BELLA
224 000
COMPLETO DONNA
8 COMPUTER SHOP
134 000
JOYSTICK
22
ABITI BELLA
79 000
PANTALONI
23 BIOGAS SRL
399 000
GAS
24 LIBRERIE CULTURA
224 000
LIBRI, CANCELLERIA
25 COMPUTER SHOP
88 000
CONTROLLER

È possibile applicare la clausola GROUP BY anche a più di un campo per volta. Vediamo come funziona:

SELECT BENEFICIARIO, NOTE
FROM ASSEGNI
GROUP BY BENEFICIARIO, NOTE;

BENEFICIARIO NOTE
------------------------------------------------------
NOTE
-----------------------
ABITI BELLA COMPLETO DONNA
ABITI BELLA PANTALONI
ASSICURAZIONI ASSO ASSICURAZIONE CASA
BIOGAS SRL GAS
COMPUTER SHOP CONTROLLER
COMPUTER SHOP DISCHETTI E CD-ROM
COMPUTER SHOP JOYSTICK
COMPUTER SHOP TELEFONO CELLULARE
GAS S.P.A. GAS
LIBRERIE CULTURA LIBRI, CANCELLERIA
SUPERMARCHET GS ALIMENTARI

In questa query le righe selezionate sono 11 contro le 15 della tabella originale, cosa è successo?
È avvenuto che la dove il beneficiario presentava le stesse note, veniva visualizzato una volta sola.
Si veda quante volte appare, nella tabella ASSEGNI, in NOTE ‘libri cancelleria’, ‘gas’(per beneficiario Biogas SRL), ‘controller’ e ‘pantaloni’.

Vediamo altri esempi:

Vogliamo sapere oltre a quanto è stato elargito per ogni beneficiario, quante volte il singolo beneficiario compare nella tabella:

SELECT BENEFICIARIO, SUM(IMPORTO), COUNT(BENEFICIARIO)
FROM ASSEGNI
GROUP BY BENEFICIARIO;

BENEFICIARIO
-----------------------------------
SUM(IMPORTO)
--------------------------
COUNT(BENEFICIARIO)
--------------------------------------
ABITI BELLA
413 000
3
ASSICURAZIONI ASSO
425 000
1
BIOGAS SRL
487 000
2
COMPUTER SHOP
506 000
5
GAS S.P.A.
25 000
1
LIBRERIE CULTURA
469 000
2
SUPERMARCHET GS
150 000
1

Abiti Bella compare nella tabella tre volte, Assicurazioni ASSO una volta, ecc.

Voglio sapere il totale dell’importo per ogni nota che facendo parte dello stesso beneficiario compaia una o più volte. Voglio sapere quante volte quella stessa nota appare per lo stesso beneficiario. Voglio inoltre visualizzare le note:

SELECT BENEFICIARIO, NOTE, SUM(IMPORTO), COUNT(BENEFICIARIO)
FROM ASSEGNI
GROUP BY BENEFICIARIO, NOTE;

BENEFICIARIO
------------------------
NOTE
----------------------------
SUM(IMPORTO)
----------------------
COUNT(BENEFICIARIO)
---------------------------------
ABITI BELLA COMPLETO DONNA
224 000
1
ABITI BELLA PANTALONI
189 000
2
ASSICURAZIONI ASSO ASSICURAZIONE CASA
425 000
1
BIOGAS SRL GAS
487 000
2
COMPUTER SHOP CONTROLLER
122 000
2
COMPUTER SHOP DISCHETTI E CD-ROM
50 000
1
COMPUTER SHOP JOYSTICK
134 000
1
COMPUTER SHOP TELEFONO CELLULARE
200 000
1
GAS S.P.A. GAS
25 000
1
LIBRERIE CULTURA LIBRI, CANCELLERIA
469 000
2
SUPERMARCHET GS ALIMENTARI
150 000
1

Nella prima riga della tabella estrapolata con la query precedente, vediamo che COUNT(BENEFICIARIO) vale 1; ciò significa che la nota ‘Completo donna’ per quel beneficiario è presente nella tabella di origine una sola volta. Mentre invece, la nota ‘Pantaloni’, sempre per il medesimo beneficiario vale 2, questo significa che quella nota per quel beneficiario è presente nella tabella ben due volte.

Adesso vogliamo estrapolare i stessi dati della query precedente, ma ordinandoli per le note.

SELECT BENEFICIARIO, NOTE, SUM(IMPORTO), COUNT(BENEFICIARIO)
FROM ASSEGNI
GROUP BY BENEFICIARIO, NOTE
ORDER BY NOTE;

BENEFICIARIO
------------------------
NOTE
----------------------------
SUM(IMPORTO)
----------------------
COUNT(BENEFICIARIO)
---------------------------------
SUPERMARCHET GS ALIMENTARI
150 000
1
ASSICURAZIONI ASSO ASSICURAZIONE CASA
425 000
1
ABITI BELLA COMPLETO DONNA
224 000
1
COMPUTER SHOP CONTROLLER
122 000
2
COMPUTER SHOP DISCHETTI E CD-ROM
50 000
1
BIOGAS SRL GAS
487 000
2
GAS S.P.A. GAS
25 000
1
COMPUTER SHOP JOYSTICK
134 000
1
LIBRERIE CULTURA LIBRI, CANCELLERIA
469 000
2
ABITI BELLA PANTALONI
189 000
2
COMPUTER SHOP TELEFONO CELLULARE
200 000
1

Per gli esempi futuri faremo riferimento alla tabella DIPENDENTI sottostante:

DIPENDENTI
NOME
--------------------
DIVISIONE
-----------------------------
STIPENDIO
------------------
GIORNI_MUTUA
-------------------------
FERIE_GODUTE
-------------------------
ROSSI VENDITE
2 000 000
33
5
BIANCHI VENDITE
2 100 000
1
0
BRUNI RICERCA
3 300 000
0
9
VERDI ACQUISTI
1 800 000
32
20
GIALLI RICERCA
4 800 000
0
0
NERI RICERCA
3 400 000
2
1
MANCINI AMMINISTRAZIONE
2 400 000
9
24
MARCHETTI VENDITE
2 000 000
99
12

HAVING

Abbiamo visto come tramite la clausola GROUP BY le righe possano venire raggruppate in sottoinsiemi. Una particolare interrogazione può avere la necessità di estrapolare solo quei sottoinsiemi di righe che soddisfano certe condizioni, in questo caso però non è possibile usare la clausola WHERE in quanto tale clausola verifica la condizione che la segue, su tutte le righe e non in maniera singola sui valori estrapolati per ogni sottoinsieme di righe.
Vediamo un esempio:

Vogliamo conoscere le medie dei stipendi per ogni divisione che superano i 2.200.000 di lire

SELECT DIVISIONE, AVG(STIPENDIO)
FROM DIPENDENTI
GROUP BY DIVISIONE
WHERE AVG(STIPENDIO) > 2200000;

ERRORE alla riga 4:
ORA-00933: comando SQL terminato erroneamente

Nella query scritta sopra possiamo vedere come la clausola WHERE sia stata posta per ultima, infatti bisogna verificare la condizione solo dopo che sono stati formati i sottoinsiemi dalla clausola GROUP BY.
Il risultato però, è comunque un avviso di errore, proprio perché non è possibile utilizzare WHERE per verificare condizioni sui risultati di funzioni di gruppo. Vediamo quindi come possiamo risolvere il problema:

SELECT DIVISIONE, AVG(STIPENDIO)
FROM DIPENDENTI
HAVING AVG(STIPENDIO) > 2200000;

DIVISIONE
-------------------------------
AVG(STIPENDIO)
---------------------------
AMMINISTRAZIONE 2 400 000
RICERCA 3 833 333,3

Come abbiamo potuto vedere dall’esempio la clausola HAVING sostituisce la clausola WHERE la dove nella condizione appaiono funzioni di gruppo o quando la condizioni deve essere verificata su sottoinsiemi di righe.

Vediamo altri esempi:

SELECT DIVISIONE, AVG(STIPENDIO)
FROM DIPENDENTI
GROUP BY DIVISIONE
HAVING DIVISIONE = 'VENDITE';

DIVISIONE
-------------------------------
AVG(STIPENDIO)
---------------------------
VENDITE 2033333,3

In questo caso è stata estrapolata la media degli stipendi della sola divisione vendite. Proviamo a ottenere lo stesso risultato usando a posto della clausola HAVING la clausola WHERE:

SELECT DIVISIONE, AVG(STIPENDIO)
FROM DIPENDENTI
GROUP BY DIVISIONE
WHERE DIVISIONE = 'VENDITE';

ERRORE alla riga 4:
ORA-00933: comando SQL terminato erroneamente

Il risultato che si ottiene è un avviso di errore, in quanto la clausola WHERE è stata messa dopo la clausola GROUP BY e quindi si è tentato di usarla non per singole righe, ma per sottoinsiemi di righe. Vediamo come si può aggirare l’ostacolo senza, comunque, usare la clausola GROUP BY:

SELECT DIVISIONE, AVG(STIPENDIO)
FROM DIPENDENTI
WHERE DIVISIONE = 'VENDITE'
GROUP BY DIVISIONE;

DIVISIONE
-------------------------------
AVG(STIPENDIO)
---------------------------
VENDITE 2033333,3

In questo caso la clausola WHERE è stata usata non sugli insiemi delle righe, in quanto posta prima della clausola GROUP BY.

Voglio conoscere la media dei giorni di ferie godute per dipartimento, ma solo di quei dipendenti che percepiscono stipendi superiori ai 2.050.000 di lire:

SELECT DIVISIONE, AVG(FERIE_GODUTE)
FROM DIPENDENTI
WHERE STIPENDIO > 2050000
GROUP BY DIVISIONE;

DIVISIONE
-----------------------
AVG (FERIE_GODUTE)
---------------------------------------
AMMINISTRAZIONE 24
RICERCA   3,3333333
VENDITE   0

In questo caso abbiamo usato la clausola WHERE in quanto la condizione va verificata per tutte le righe e non per singoli valori estrapolati da singoli sottoinsiemi di righe.

Adesso vogliamo escludere dal risultato della query precedente quelle divisioni la cui media delle ferie godute, calcolata solo per quei dipendenti il cui stipendio supera i 2.050.000 di lire, è uguale a zero:

SELECT DIVISIONE, AVG(FERIE_GODUTE)
FROM DIPENDENTI
WHERE STIPENDIO > 2050000
GROUP BY DIVISIONE
HAVING AVG(FERIE_GODUTE) <> 0;

DIVISIONE
-----------------------
AVG (FERIE_GODUTE)
---------------------------------------
AMMINISTRAZIONE 24
RICERCA   3,3333333

Riepilogo

Dagli esempi precedenti, dalle cose che sono state dette e da eventuali esperimenti che potremmo fare, possiamo enunciare degli assiomi che riguardano l’uso delle clausole viste in questo capitolo:

  1. WHERE non può essere usato per verificare condizioni su risultati di funzioni di gruppo.
  2. WHERE non può essere usato per verificare condizioni su sottoinsiemi delle varie righe.

 

  1. GROUP BY tutte le colonne che vengono selezionate (colonne che seguono la clausola SELECT) devono essere elencate nella clausola GROUP BY.

 

  1. HAVING può essere seguita da una o più funzioni di gruppo e verificare condizioni su i valori ritornati. da tali funzioni.
  2. HAVING può verificare condizioni sui valori dei sottoinsiemi creati dalla clausola GROUP BY.
  3. HAVING può verificare condizioni combinate sui valori dei sottoinsiemi creati dalla clausola GROUP BY e condizioni sui valori ritornati da funzioni di gruppo.
  4. HAVING i campi che vi appaiono devono essere specificati nella clausola GROUP BY
  5. HAVING è necessario, per il suo utilizzo, la presenza della clausola GROUP BY.
  6. HAVING non è necessario che venga posta dopo la clausola GROUP BY.

 

  1. ORDER BY è necessario che venga posta dopo la clausola GROUP BY e dopo la clausola HAVING.

Riassumendo vediamo come può essere la forma sintetica di una query che fa uso delle clausole viste in questo capitolo:

select lista attributi o espressioni
from lista tabelle
[where condizioni semplici]
[group by lista attributi di raggruppamento]
[having condizioni aggregate]
[order by lista attributi di ordinamento]


 
Precedente
Segue
pag. 8 di 20

Un dispensa sulle clausole utilizzate con l'istruzione SELECT in SQL della Art Net ( leggere le note legali ) - 06/02/2006

webmaster: BWD

Valid HTML 4.01!  Valid CSS!

Il sito web che puoi costruire tu con articoli, dispense, il blog ed altro!
• DISPENSE DI INFORMATICA - SQL (Structured Query Language)