Basi di Dati S Q L Lezione 4 Antonio Virdis a.virdis@iet.unipi.it
Sommario Espressioni condizionali Query nella SELECT Raggruppamento di tuple Condizioni sui gruppi 2
Esercizio 6 (lezione 3) Indicare nome e cognome dei pazienti che non sono mai stati visitati da un proprio compaesano SELECT p.nome, p.cognome FROM paziente p WHERE NOT EXISTS ( SELECT * FROM medico m JOIN visita v ON m.matricola=v.medico WHERE m.citta=p.citta AND v.paziente=p.codfiscale )? Medici che hanno visitato compaesani 3
Espressioni Condizionali E' possibile generare valori sulla base di espressioni condizionali Ciò si ottiene tramite la direttiva CASE SELECT attr1, CASE attr2 WHEN condizione1 THEN espressione1 {WHEN condizione2 THEN espressione2} ELSE espressione3 END 4
Esempio: CASE Indicare la parcella al netto delle tasse per tutti i medici che risiedono in città di cui tali tasse sono note, NULL per tutti gli altri. (Pisa =10, Firenze=50) SELECT Cognome, CASE citta WHEN 'pisa' THEN parcella-10 WHEN 'firenze' THEN parcella-50 ELSE NULL END AS parcelladetassata FROM medico 5
Esempio: query nella SELECT Specificare per ogni paziente nome, cognome e la differenza di reddito tra lui e quello più ricco. SELECT Cognome, Nome, ( SELECT MAX(reddito) FROM paziente ) - reddito AS 'Differenza Reddito' FROM paziente 6
Raggruppamento Un insieme di tuple può essere diviso in sottoinsiemi L'appartenenza ad un sottoinsieme viene decisa sulla base di uno o più attributi comuni Ciò si ottiene mediante la clausola GROUP BY SELECT attr1, attr2 FROM... WHERE... GROUP BY (attr1, attr2, attr3) 7
Raggruppamento(2) Finora abbiamo utilizzato gli operatori aggregati su tutte le tuple risultato di una query Tali operatori possono lavorare separatamente su sottoinsiemi 8
Esempio GROUP BY Indicare per ogni città il numero di pazienti maschi che vi risiedono SELECT citta, COUNT(*) AS residenti FROM paziente 1 WHERE sesso='m' GROUP BY citta 3 Pisa Roma Grosseto 4 NOME CITTA' SESSO Carlo Pisa M Marta Firenze F Giovannina Pisa F Alberto Roma M Franco Grosseto M Gina Milano F Alessandro Grosseto M 9 2
Esercizio 1 Indicare per ogni specializzazione, il numero di visite effettuate SELECT specializzazione, COUNT(*) FROM medico JOIN visita ON medico=matricola GROUP BY specializzazione 10
Esercizio 2 Indicare per ogni specializzazione, il numero di pazienti unici visitati SELECT specializzazione, COUNT(distinct paziente) FROM medico JOIN visita ON medico=matricola GROUP BY specializzazione 11
Esercizio 3 Indicare per ogni specializzazione, il guadagno del 2012 SELECT specializzazione, SUM(parcella) FROM medico JOIN visita ON medico=matricola WHERE YEAR(data)=2012 GROUP BY specializzazione 12
Esercizio 4 Indicare per ogni citta, il reddito medio dei pazienti SELECT citta, AVG(reddito) FROM paziente GROUP BY citta 13
Condizioni sui gruppi E' possibile filtrare i gruppi che andranno a far parte del risultato Tramite la clausola HAVING specifichiamo delle condizioni che devono essere rispettate a livello di gruppo SELECT attr1, attr2 FROM... WHERE... GROUP BY attr1, attr2, attr3 HAVING condizione 14
Clausola HAVING Descrive le condizioni che si devono applicare al termine di una interrogazione che fa uso della clausola GROUP BY Ogni gruppo creato dalla GROUP BY fa parte del risultato solo se la condizione della è HAVING soddisfatta La HAVING spera di ricevere come input un espressione booleana In genere dovrebbero far parte di tale espressione solo operatori aggregati 15
Esercizio 5 Indicare nome e cognome dei medici che hanno svolto meno di 16 visite in carriera SELECT nome, cognome FROM medico JOIN visita ON medico=matricola GROUP BY matricola HAVING COUNT(*)<16 E se volessi solo quelli di Firenze??? WHERE HAVING 16
Esercizio 6 Indicare nome e cognome dei medici che hanno visitato meno di 16 pazienti unici in carriera SELECT nome, cognome FROM medico JOIN visita ON medico=matricola GROUP BY matricola HAVING COUNT(distinct paziente)<16 17
Esercizio 7 Indicare il giorno dell'anno con più visite. (*) Cosa vado a fissare? Quello che ho fissato è chiave? Che caratteristica devono avere i risultati buoni? Come traduco questa caratteristica? 18
Esercizio 7 Indicare il giorno dell'anno con in cui sono state effettuate più visite rispetto a tutti gli altri. (*) SELECT DAY(data) AS giorno, MONTH(data) AS mese FROM visita GROUP BY DAY(data), MONTH(data) HAVING COUNT(*)>=ALL ( SELECT COUNT(*) FROM visita GROUP BY DAY(data), MONTH(data) ) 19
Esercizio Minaccioso Indicare la città dove abita il paziente più ricco Soluzione dolorosamente sbagliata SELECT citta FROM paziente GROUP BY citta HAVING MAX(reddito) SELECT citta FROM paziente GROUP BY citta HAVING 1000...eh? 20
Esercizio Minaccioso Indicare la città dove abita il paziente più ricco SELECT citta FROM paziente GROUP BY citta HAVING MAX(reddito)= ( SELECT MAX(reddito) FROM paziente ) 21
Esercizio 8 Nome e Cognome dei medici che hanno visitato tutti i pazienti di Pisa (si ritengono pazienti quelli che sono stati visitati almeno una volta) create or replace view pisani(codfiscale) as SELECT CodFiscale FROM paziente WHERE citta='pisa'; 22
SELECT nome, cognome FROM medico Definisco signor X WHERE matricola IN ( SELECT medico FROM visita WHERE paziente in ( Pisani visitati da X SELECT * FROM pisani ) GROUP BY medico HAVING COUNT(distinct paziente)= ( SELECT COUNT(distinct paziente) FROM visita WHERE paziente in ( SELECT * Pisani visitati FROM pisani ) ) ) 23
Esercizio 9 Indicare nome e cognome, spesa e reddito annuali dei pazienti che nel 2012 hanno speso più del 5% del loro reddito 24
Esercizio 9 Indicare nome e cognome, spesa e reddito annuali dei pazienti che nel 2012 hanno speso più del 5% del loro reddito create or replace view spesa2012(paziente,spesa) as SELECT paziente,sum(parcella) FROM visita JOIN medico ON medico=matricola WHERE YEAR(data)=2012 GROUP BY paziente ; SET @perc = 5; 25
SELECT nome, cognome, ( SELECT spesa FROM spesa2012 WHERE paziente=codfiscale ) AS spesa2012, ((reddito*12)/100)*@perc AS PercentualeReddito FROM paziente p WHERE ( SELECT s.spesa FROM spesa2012 s WHERE s.paziente=p.codfiscale ) > ((reddito*12)/100)*@perc 26