SQL SQL come Data Manipulation Language - Funzioni Aggregate e GROUP BY
Esempio DB 1 Madre Maternita Figlio Nome Eta Andrea 27 Aldo 25 Maria 55 Anna 50 Filippo 26 Luigi 50 Franco 60 Olga 30 Sergio 85 Luisa 75 Persone Reddito 21 15 42 35 30 40 20 41 35 87 Padre Sergio Luigi Luigi Franco Franco Paternita Luisa Luisa Anna Anna Maria Maria Figlio Franco Olga Filippo Andrea Aldo Maria Luigi Olga Filippo Andrea Aldo 2
Esempio DB 2 Nome Cognome Mario Rossi Carlo Bianchi Giuseppe Verdi Franco Neri Carlo Rossi Lorenzo Lanzi Paola Borroni Marco Franco Impiegato Dipartimento Dipart Amministrazione Produzione Amministrazione Distribuzione Direzione Direzione Amministrazione Produzione Nome Amministrazione Produzione Distribuzione Direzione Ricerca Ufficio Stipendio 10 45 20 36 20 40 16 45 14 80 7 73 75 40 20 46 Indirizzo Citta Via Tito Livio Piazza Lavater Via Segre Via Tito Livio Via Morone Milano Torino Roma Milano 3 Milano
Necessità di operatori su tuple Nelle interrogazioni viste finora le condizioni di selezione (Clausola Where) venivano valutate su ciascuna tupla indipendentemente da tutte le altre. Questo e lo stesso comportamento dell algebra relazionale. Si puo ad esempio verificare se un impiegato recepisce un certo stipendio. Ma non si puo contare il numero di impiegati di un certo dipartimento, perche occorrerebbe poter manipolare un insieme di tuple. A questo scopo SQL mette a disposizione gli operatori aggregati. 4
Esempio di operatore aggregato: count select count(*) AS numeroimpiegati from Impiegato where Dipart = Produzione numeroimpiegati 2 5
Valutazione di operatore aggregato (1) Quando si utilizzano operatori aggregati, prima si valuta la query senza operatore. select * from Impiegato where Dipart = Produzione Nome Cognome Dipart Ufficio Stipendio Carlo Bianchi Produzione 20 36 Marco Franco Produzione 20 46 6
Valutazione di operatore aggregato (2) Poi si considerano le tuple come un insieme. select count(*) AS numeroimpiegati from Impiegato where Dipart = Produzione Nome Cognome Dipart Ufficio Stipendio Carlo Bianchi Produzione 20 36 Marco Franco Produzione 20 46 7
COUNT COUNT puo anche riferirsi a singoli attributi (il motivo sara piu chiaro tra poco). select count(*) AS numeroimpiegati from Impiegato numeroimpiegati 8 select count(stipendio) AS numerostipendi from Impiegato numerostipendi 8 8
COUNT Si valuta esattamente allo stesso modo. select count(stipendio) AS numerostipendi from Impiegato Stipendio 45 36 40 45 80 73 40 46 9
COUNT Se si vogliono considerare solo i valori distinti, si puo utilizzare l opzione distinct. select count(stipendio) AS numerostipendi from Impiegato numerostipendi 8 select count(distinct Stipendio) AS StipDiversi from Impiegato StipDiversi 6 10
COUNT Questo equivale alla valutazione della query con l opzione distinct, per poi applicare come al solito l operatore aggregato. select distinct Stipendio from Impiegato Stipendio 45 36 40 80 73 46 11
COUNT e valori nulli Attenzione ai valori nulli quando si specificano gli attributi su cui contare le righe. ImpiegatoConNulli Nome Cognome Dipart Ufficio Stipendio Mario Rossi Amministrazione 10 45 Carlo Bianchi Produzione 20 36 Giuseppe Verdi Amministrazione 20 40 Franco Neri Distribuzione 16 45 Carlo Rossi Direzione 14 80 Lorenzo Lanzi Direzione 7 null Paola Borroni Amministrazione 75 null Marco Franco Produzione 20 null 12
COUNT e valori nulli select count(*) AS numeroimpiegati from ImpiegatoConNulli numeroimpiegati 8 select count(stipendio) AS numerostipendi from ImpiegatoConNulli numerostipendi 5 13
Altri operatori Quanto detto per COUNT vale anche per gli operatori: sum, max, min, avg. Questi operatori escludono opportunamente i valori nulli. L opzione distinct puo ancora essere utilizzata. Altri operatori esistono (varianza, mediano...), ma non sono standard. Controllare il manuale del sistema che si vuole utilizzare. 14
Altri operatori select max(stipendio) AS stipendiomax from Impiegato stipendiomax 80 select min(stipendio) AS stipendiomin from Impiegato stipendiomin 36 15
Altri operatori select sum(stipendio) AS sommastipendi from Impiegato sommastipendi 405 select avg(stipendio) AS mediastipendi from Impiegato mediastipendi 50.625 16
Operatori aggregati e Join Gli operatori aggregati si possono utilizzare anche in concomitanza con i join. select max(stipendio) AS stipendiomassimo from Impiegato, Dipartimento D where Dipart = D.Nome AND Citta = Milano stipendiomassimo 80 17
Operatori aggregati e ridenominazione Se non utilizziamo la AS, il risultato non ha nome. select max(stipendio) from Impiegato, Dipartimento D where Dipart = D.Nome AND Citta = Milano 80 18
Operatori aggregati e target list ATTENZIONE. Quando si utilizza un operatore aggregato consideriamo insiemi di tuple. La seguente query e scorretta. select Cognome, Nome, min(stipendio) from Impiegato where Dipart = Amministrazione Nome Cognome Dipart Ufficio Stipendio Mario Rossi Amministrazione 10 45 Giuseppe Verdi Amministrazione 20 40 Paola Borroni Amministrazione 75 40 19
Interrogazioni con raggruppamento Gli operatori aggregati vengono applicati ad un insieme di righe. Gli esempi visti operano su tutte le righe. Spesso esiste l esigenza di applicare operatori aggregati distintamente ad insiemi di tuple. Ad esempio: per ogni dipartimento, trovare la somma degli stipendi. 20
Operatori aggregati e raggruppamenti Per ogni dipartimento, la somma degli stipendi Selezioniamo il dipartimento e gli stipendi. Dipart Amministrazione Produzione Amministrazione Distribuzione Direzione Direzione Amministrazione Produzione Stipendio 45 36 40 45 80 73 40 46 21
Operatori aggregati e raggruppamenti Per ogni dipartimento, la somma degli stipendi Raggruppiamo per dipartimento. Dipart Amministrazione Amministrazione Amministrazione Produzione Produzione Distribuzione Direzione Direzione Stipendio 45 40 40 36 46 45 80 73 22
Operatori aggregati e raggruppamenti Per ogni dipartimento, la somma degli stipendi Calcoliamo la somma. Dipart Amministrazione Produzione Distribuzione Direzione 125 82 45 153 23
Operatori aggregati e raggruppamenti Per ogni dipartimento, la somma degli stipendi select Dipart, sum(stipendio) AS TotaleStipendi from Impiegato GROUP BY Dipart Dipart Amministrazione Produzione Distribuzione Direzione TotaleStipendi 125 82 45 153 24
Passo a passo Per ogni dipartimento, la somma degli stipendi select Dipart, Stipendio from Impiegato Dipart Stipendio Amministrazione 45 Produzione 36 Amministrazione 40 Distribuzione 45 Direzione 80 Direzione 73 Amministrazione 40 Produzione 46 25
Passo a passo Per ogni dipartimento, la somma degli stipendi select Dipart, Stipendio from Impiegato Dipart Stipendio Group By Dipart Amministrazione Amministrazione Amministrazione Produzione Produzione Distribuzione Direzione Direzione 45 40 40 36 46 45 80 73 26
Passo a passo Per ogni dipartimento, la somma degli stipendi select Dipart, sum(stipendio) As TotaleStipendi from Impiegato Group By Dipart Dipart Amministrazione Produzione Distribuzione Direzione TotaleStipendi 125 82 45 153 27
Operatori aggregati e target list ATTENZIONE: nel momento in cui si utilizzano funzioni aggregate, si stanno considerando insiemi di tuple, non singole tuple. Di conseguenza, non e possibile utilizzare nella target list attributi non utilizzati per il raggruppamento. Infatti, questi attributi possono presentare piu valori per ogni insieme di tuple. Non e quindi possibile ottenere un singolo valore per ogni gruppo di tuple. 28
Operatori aggregati e target list Ad esempio, la seguente interrogazione NON HA SENSO: select Cognome, Dipart, sum(stipendio) from Impiegato Group By Dipart Cognome Rossi Verdi Borron Dipart Amministrazione 125 Quale cognome bisogna scegliere? Bianchi Franco Neri Produzione Distribuzione 82 45 Rossi Lanzi Direzione 29 153
Operatori aggregati e target list Le interrogazioni che abbiamo visto precedentemente, con funzioni aggregate e senza Group By, possono essere pensate come query in cui il Group By ha prodotto un solo insieme. Continua dunque a valere la regola di non utilizzare attributi nella target list non usati per il raggruppamento. Poiche in assenza del Group By nessun attributo viene utilizzato per il raggruppamento, se si utilizzano funzioni aggregate non si possono specificare altri attributi nella target list. 30
Operatori aggregati e target list Query corretta: select min(stipendio), max(stipendio) from Impiegato Query NON corretta: select Cognome, max(stipendio) from Impiegato 31
Operatori aggregati e target list Questa limitazione puo talvolta sembrare eccessiva. Ad esempio, la seguente ragionevole query NON e corretta: select Dipart, count(*), Citta from Impiegato I Join Dipartimento D on I.Dipart = D.Nome group by Dipart 32
Operatori aggregati e target list Il problema e facilmente risolto raggruppando su tutti gli attributi utilizzati direttamente nella target list. select Dipart, count(*), Citta from Impiegato I Join Dipartimento D on I.Dipart = D.Nome group by Dipart, Citta 33
Condizioni sui gruppi Ovviamente, anche utilizzando GROUP BY e possibile filtrare le tuple sulla base di predicati. Ad esempio: select min(stipendio), max(stipendio) from Impiegato where Ufficio = 20 group by Dipart 34
Condizioni sui gruppi Se le condizioni sono da calcolare sui raggruppamenti di tuple, si utilizza la clausola HAVING. Cio accade quando le condizioni utilizzano funzioni aggregate. select Dipart, sum(stipendio) from Impiegato group by Dipart HAVING sum(stipendio) > 100 Dipart Amministrazione Direzione 125 153 35
Where o Having? Per decidere se specificare le condizioni nella clausola Where o tramite Having la regola semplice: Se bisogna utilizzare una funzione aggregata, significa che la condizione concerne gli insiemi di tuple: Having. In caso contrario: Where. 36
Where o Having? I dipartimenti per cui la media degli stipendi degli impiegati che lavorano nell'ufficio 20 è superiore a 25 milioni select Dipart from Impiegato where Ufficio = 20 group by Dipart having avg(stipendio) > 25 37
Riassumiamo SelectSQL ::= select ListaAttributiOEspressioni from ListaTabelle [ where CondizioniSemplici ] [ group by ListaAttributiDiRaggruppamento ] [ having CondizioniAggregate ] [ order by ListaAttributiDiOrdinamento ] 38
SQL SQL come Data Manipulation Language - Operatori insiemistici
Necessita di operatori insiemistici Assumiamo di volere elencare in una tabella i nomi dei padri e delle madri. Non siamo in grado di farlo utilizzando quanto imparato finora. Padre Sergio Luigi Luigi Franco Franco Madre Luisa Luisa Anna Anna Maria Maria 40
Necessita di operatori insiemistici Abbiamo bisogno di un operatore di unione, che possa produrre come risultato una tabella in cui sono elencate le righe ottenute da piu Select. Padre Sergio Luigi Luigi Franco Franco Madre Luisa Luisa Anna Anna Maria Maria 41
SELECT Padre Unione FROM Paternita UNION SELECT Madre FROM Maternita Padre Sergio Luigi Franco Luisa Anna Maria 42
SELECT Padre Unione: considerazioni FROM Paternita UNION SELECT Madre FROM Maternita Padre Sergio Luigi Franco Luisa Anna Maria Gli operatori insiemistici eliminano i duplicati. 43
Unione: considerazioni SELECT Padre FROM Paternita UNION ALL SELECT Madre FROM Maternita L opzione ALL li mantiene. Padre Sergio Luigi Luigi Franco Franco Luisa Luisa Anna Anna Maria Maria 44
SELECT Padre Unione: considerazioni FROM Paternita UNION SELECT Madre FROM Maternita Padre Sergio Luigi Franco Luisa Anna Maria Il nome utilizzato e tipicamente quello del primo select (si potrebbe decidere di non utilizzare alcun nome) 45
Notazione Posizionale select Padre, Figlio from Paternita union select Madre, Figlio from Maternita Padre Sergio Luigi Luigi Franco Franco Madre Luisa Luisa Anna Anna Maria Maria Figlio Franco Olga Filippo Andrea Aldo Figlio Maria Luigi Olga Filippo Andrea Aldo 46
Notazione Posizionale select Padre, Figlio from Paternita union select Figlio, Madre from Maternita Padre Sergio Luigi Luigi Franco Franco Figlio Maria Luigi Olga Filippo Andrea Aldo Figlio Franco Olga Filippo Andrea Aldo Madre Luisa Luisa Anna Anna Maria Maria 47
Notazione Posizionale Anche con le ridenominazione non cambia nulla: e sempre l ordine a contare. select Padre AS genitore, Figlio from Paternita union select Figlio, Madre AS genitore from Maternita 48
Intersezione L intersezione e analoga: select Nome from Impiegato intersect select Cognome from Impiegato Otteniamo: Nome Franco Nome Mario Carlo Giuseppe Franco Carlo Lorenzo Paola Marco Cognome Rossi Bianchi Verdi Neri Rossi Lanzi Borroni Franco 49
Intersezione A differenza dell unione, questa query e esprimibile senza utilizzare esplicitamente l operatore insiemistico: select I1.Nome from Impiegato I1, Impiegato I2 where I1.Nome = I2.Cognome 50
Differenza Idem per la differenza: select Nome from Impiegato except Nome Mario select Cognome Carlo from Impiegato Giuseppe Otteniamo: Carlo Lorenzo Paola Marco 51
Differenza Anche questa query e esprimibile senza utilizzare esplicitamente l operatore insiemistico. Occorre pero utilizzare una struttura piu complessa, composta da due Select annidati. Nella prossima sezione vedremo come scrivere questo tipo di query. 52
SQL SQL come Data Manipulation Language - Interrogazioni nidificate
Interrogazioni nidificate Abbiamo in precedenza mostrato come la seguente interrogazione sia errata: select Cognome, max(stipendio) from Impiegato L intento e quello di selezionare il cognome dell impiegato/i che guadagna di piu, con il proprio stipendio. Questo e facilmente realizzabile tramite due query. 54
Interrogazioni nidificate Prima troviamo lo stipendio massimo: select Cognome from Impiegato where Stipendio = (select max(stipendio) from Impiegato) 80 55
Interrogazioni nidificate Poi cerchiamo gli impiegati il cui stipendio e uguale al massimo: select Cognome from Impiegato where Stipendio = (select max(stipendio) from Impiegato) 56
Interrogazioni nidificate: un altro esempio Nome e reddito del padre di Mario select Nome, Reddito from Persone where Nome = (select Padre from Paternita where Figlio = 'Mario') Padre di Mario 57
Interrogazioni nidificate: un altro esempio Nome e reddito del padre di Mario select Nome, Reddito from Persone where Nome = (select Padre from Paternita where Figlio = 'Mario') 58
Interrogazioni nidificate: un altro esempio Una soluzione alternativa, senza nidificazione, e la seguente: select Nome, Reddito from Persone, Paternita where Nome = Padre and Figlio = 'Mario' 59
any/all Negli esempi precedenti era chiaro che il risultato del blocco piu interno avrebbe restituito un unica tupla. In generale, non e cosi. Si deve confrontare un attributo con un insieme di tuple. Vengono quindi utilizzati operatori insiemistici esistenziali: any e all. 60
any/all Gli impiegati che lavorano in dipartimenti di Roma Cioe : che lavorano in almeno uno dei dipartimenti di Roma. select * from Impiegato where Dipart = any (select Nome from Dipartimento where Citta = 'Roma') 61
any/all I dipartimenti in cui non lavorano impiegati di cognome Rossi Cioe : diverso da tutti i dipartimenti in cui lavora un Rossi. select * from Dipartimento where Nome <>all (select Dipart from Impiegato where Cognome = Rossi ) 62
any/all In generale, where Attributo θ all (select...) E vero quando Attributo soddisfa la relazione θ (<,<=,>,>=,=,<>) con tutte le tuple resituite da (select...). where Attributo θ any (select...) E vero quando Attributo soddisfa la relazione θ con almeno una delle tuple. 63
any/all ESERCIZIO: Esprimere le ultime due interrogazioni senza utilizzare la nidificazione. 64
in / not in SQL mette a disposizione anche gli operatori in, e not in, che sono equivalenti a =any e <>all. select * from Impiegato where Dipart in (select Nome from Dipartimento where Citta = 'Roma') select * from Dipartimento where Nome not in (select Dipart from Impiegato where Cognome = Rossi ) 65
Interrogazioni nidificate, commenti La prima versione di SQL prevedeva solo la forma nidificata (o strutturata), con una sola relazione in ogni clausola FROM. Il che è insoddisfacente: La dichiaratività è limitata. Non si possono includere nella target list attributi di relazioni nei blocchi interni. La forma nidificata è meno dichiarativa, ma talvolta più leggibile (richiede meno variabili). La forma piana e quella nidificata possono essere combinate. Le sottointerrogazioni non possono contenere operatori insiemistici ( l unione si fa solo al livello esterno ). La limitazione non è significativa. 66
Interrogazioni piatte o nidificate? Spesso ad una query nidificata ne corrisponde una piatta. La scelta deve essere guidata in primis dalla leggibilita, in quanto sara poi il sistema a scegliere un piano di esecuzione efficiente. 67
Interrogazioni piatte o nidificate? Nome e reddito dei padri di persone che guadagnano più di 20 milioni" select Nome, Reddito from Persone where Nome in (select Padre from Paternita where Figlio =any (select Nome from Persone where Reddito > 20)) select distinct P.Nome, P.Reddito from Persone P, Paternita, Persone F where P.Nome = Padre and Figlio = F.Nome and F.Reddito > 20 68
Interrogazioni piatte o nidificate? Nome degli impiegati che si chiamano come un impiegato di Produzione" select I1.Nome from Impiegato I1, Impiegato I2 where I1.Nome = I2.Nome and I2.Dipart = 'Produzione' select Nome from Impiegato where Nome = any (select Nome from Impiegato where Dipart = 'Produzione') 69
Operatore exists Un ulteriore operatore insiemistico e exists. Si puo utilizzare per verificare se il risultato di una query interna e vuoto. 70
Operatore exists Le persone che hanno almeno un figlio select * from Persone where exists (select * from Paternita where Padre = Nome) or exists (select * from Maternita where Madre = Nome) 71
Operatore exists Nome Andrea Aldo Maria Anna Filippo Luigi Franco Olga Sergio Luisa Le persone che hanno almeno un figlio select * from Persone where exists (select * from Paternita where Padre = Nome) or exists (select * from Maternita where Madre = Nome) Padre Sergio Luigi Luigi Franco Franco Madre Luisa Luisa Anna Anna Maria 72 Maria
Operatore exists Nome Andrea Aldo Maria Anna Filippo Luigi Franco Olga Sergio Luisa Le persone che hanno almeno un figlio select * from Persone where exists (select * from Paternita where Padre = Nome) or exists (select * from Maternita where Madre = Nome) Padre Sergio Luigi Luigi Franco Franco Madre Luisa Luisa Anna Anna Maria 73 Maria
Operatore exists Nome Andrea Aldo Maria Anna Filippo Luigi Franco Olga Sergio Luisa Le persone che hanno almeno un figlio select * from Persone where exists (select * from Paternita where Padre = Nome) or exists (select * from Maternita where Madre = Nome) Padre Sergio Luigi Luigi Franco Franco Madre Luisa Luisa Anna Anna Maria 74 Maria
Operatore exists Nome Andrea Aldo Maria Anna Filippo Luigi Franco Olga Sergio Luisa Le persone che hanno almeno un figlio select * from Persone where exists (select * from Paternita where Padre = Nome) or exists (select * from Maternita where Madre = Nome) Padre Sergio Luigi Luigi Franco Franco Madre Luisa Luisa Anna Anna Maria 75 Maria
Semantica delle espressioni correlate L interrogazione interna viene eseguita una volta per ciascuna ennupla dell interrogazione esterna. select Attributo from Tabella where exists (select Select * from From Paternita... where Padre = Nome) Where Attributo... 76
Esempio di utilizzo di exists Trovare i padri i cui figli guadagnano tutti più di venti milioni" select distinct Padre from Paternita Z where not exists (select * from Paternita W, Persone where W.Padre = Z.Padre and W.Figlio = Nome and Reddito <= 20) 77
exists per specificare una differenza select Nome from Impiegato except select Cognome as Nome from Impiegato select Nome from Impiegato I where not exists (select * from Impiegato where Cognome = I.Nome) 78
exists per specificare un unione select * from Persone where Reddito > 30 union select F.* from Persone F, Paternita, Persone P where F.Nome = Figlio and Padre = P.Nome and P.Reddito > 30 select * from Persone F where Reddito > 30 or exists (select * from Paternita, Persone P where F.Nome = Figlio and Padre = P.Nome and P.Reddito > 30) 79
Regole di visibilità: Visibilità Non è possibile fare riferimenti a variabili definite in blocchi più interni Se un nome di variabile è omesso, si assume riferimento alla variabile più vicina Nota: in un blocco si può fare riferimento a variabili definite in blocchi più esterni. L interrogazione interna va ripetuta una volta per ciascun valore della variabile. 80
Visibilità La seguente query e scorretta, in quanto D1 e visibile solo nel blocco in cui e dichiarata: select * from Impiegato Visibilita di D1 where Dipart in (select Nome from Dipartimento D1 where Nome = 'Produzione') or Dipart in (select Nome from Dipartimento D2 where D2.Citta = D1.Citta) 81