Interrogazioni di tipo insiemistico SQL fornisce anche gli operatori di tipo insiemistico union, intersect, except (minus) con la seguente sintassi: SelectSQL {< union|intersect|except >[all]} SelectSQL • intersect e except potrebbero anche essere derivati attraverso opportune query • gli operatori insiemistici eseguono per default una eliminazione dei duplicati; all specifica di non farla • gli schemi su cui si opera non devono essere identici come nell’algebra relazionale ma avere uguale numero di attributi e domini compatibili. La corrispondenza è per posizione. Interrogazioni di tipo insiemistico Estrarre nomi e cognomi degli impiegati select Nome from Impiegato union select Cognome from Impiegato Estrarre i cognomi degli impiegati che sono anche nomi select Nome from Impiegato intersect select Cognome from Impiegato Interrogazioni nidificate Interrogazioni nidificate E’ possibile anche realizzare clausole where in cui il confronto non avviene fra predicati semplici o fra valori, ma fra valori e insiemi di valori, appartenenti allo stesso dominio, che sono risultato di un’altra interrogazione. select I.Nome, Cognome from Impiegato I where Dipart = any (select D.Nome from Dipartimento D where Città=‘Firenze’) SQL offre 2 possibilità di estendere gli operatori di confronto al caso del confronto valore/insieme (risultato query): Il risultato comprende: all specifica che il risultato del confronto è vero se è vero per tutte le righe del risultato dell’interrogazione. tutte le righe di IMPIEGATO per cui il valore Dipart è uguale ad almeno uno dei valori di Nome in DIPARTIMENTO, limitatamente alle tuple per cui Città=‘Firenze’, any specifica che il risultato del confronto è vero se è vero per una qualunque riga del risultato dell’interrogazione. cioè l’elenco degli impiegati che lavorano in dipartimenti con sede a Firenze. 1 Interrogazioni nidificate Lo stesso risultato si poteva ottenere con un join, ma così, specialmente per interrogazioni complesse, è più leggibile. select I.Nome, Cognome from Impiegato I where Dipart = any ( select D.Nome from Dipartimento D where Città = ’Firenze’) select I.Nome, Cognome from Impiegato I, Dipartimento D where Dipart = D.Nome and Città = ’Firenze’ Interrogazioni nidificate L’uso delle interrogazioni nidificate può anche eliminare la necessità degli alias. Es. select I1.Nome from Impiegato I1, Impiegato I2 where I1.Nome = I2.Nome and I1.Dipart = ’Produz’ and I2.Dipart <> ’Produz’ equivale a select Nome from Impiegato where Nome = any (select I.Nome from Impiegato I where I.Dipart=’Produz’) and Dipart <> ’Produz’ Nome e reddito del padre di Franco select Nome, Reddito from Persone, Paternita where Nome = Padre and Figlio = 'Franco' select Nome, Reddito from Persone where Nome =(select Padre from Paternita where Figlio = 'Franco') Interrogazioni nidificate Non tutte le interrogazioni nidificate corrispondono però ad un join select Nome from Dipartimento where Nome <> all ( select Dipart from Impiegato where Cognome=‘Rossi’) La condizione è verificata per le righe che NON contengono un certo valore, quindi non è esprimibile mediante un join, che richiede una corrispondenza fra valori. Però è equivalente a : P Nome(DIPARTIMENTO) - P Dipart (s Cognome=‘Rossi’(IMPIEGATO))) e quindi le due query potevano essere unite da except NB: =any e <>all si possono anche scrivere in e not in 2 Operatori aggregati e nidificazione • La persona (o le persone) con il reddito massimo select * from persone where reddito = ( select max(reddito) from persone ) Operatori aggregati e nidificazione select from where Dipart, Stipendio Impiegato Stipendio = ( select max(Stipendio) from Impiegato ) equivale a select Dipart, Stipendio from Impiegato where Stipendio >= all ( select Stipendio from Impiegato (n.b. il massimo di un insieme è il valore, appartenente a quell’insieme, che è maggiore o uguale a tutti gli altri) Operatori aggregati e nidificazione Interpretazione delle query nidificate Attenzione: un operatore aggregato non può essere applicato ad un altro operatore aggregato. Ad es., non posso utilizzare max se voglio calcolare il massimo fra i risultati di un operatore aggregato applicato ai sottoinsiemi definiti con la clausola group by. In questo caso è obbligatorio usare un confronto fra valori di due sottoinsiemi (spesso uguali) Per analizzare il risultato di una interrogazione nidificata si può supporre di valutare prima il risultato dell’interrogazione nidificata e poi quella della interrogazione che la contiene. select Dipart, sum(Stipendio) as MaxSumSt from Impiegato group by Dipart having MaxSumSt >=all (select sum(Stipendio) from Impiegato group by Dipart ) In questo caso bisogna usare la definizione ‘procedurale’ di query, che calcola il prodotto cartesiano fra le tabelle e poi verifica la condizione where separatamente per ogni riga. Questo migliora anche l’efficienza, in quanto l’interrogazione nidificata viene eseguita una sola volta. Talvolta però esiste una dipendenza tramite variabile (passaggio di binding) fra l’interrogazione nidificata e quella che la contiene. Quindi per ogni riga della query esterna (da cui dipende anche la query interna) si valuta prima la query nidificata per poi calcolare il predicato a livello di riga sulla query esterna. 3 Interrogazioni nidificate Le variabili SQL sono utilizzabili solo nella query in cui sono definite o nell’ambito di una query nidificata al suo interno. Se due query sono allo stesso livello non possono condividere variabili. exists è un operatore logico applicabile a query nidificate. Restituisce vero se la query dà un risultato non nullo, falso se è nullo. E’ utilizzabile in modo significativo solo se esiste un passaggio di binding fra interrogazione esterna e interrogazione nidificata. Le persone che hanno almeno un figlio select * from Persone P where exists ( select * from Paternita where Padre = P.Nome) or exists ( select * from Maternita where Madre = P.Nome) exists Costruttore di tuple select * from Persona P where exists ( select * from Persona P1 where P1.Nome = P.Nome and P1.Cognome = P.Cognome and P1.Cfiscale <> P.CFiscale) Quando si deve valutare una condizione che coinvolge un insieme di attributi, la lista degli attributi coinvolti viene inserita all’interno di una parentesi tonda. In questo caso non è possibile eseguire prima la query nidificata, in quanto è indeterminata se non si risolve il riferimento. Quindi per ogni riga dell’interrogazione esterna dovrà essere valutata l’interrogazione nidificata. Es. select * from Persona P where (Nome, Cognome) in ( select Nome, Cognome from Persona Q where P.CFiscale <> Q.CFiscale) 4
© Copyright 2024 Paperzz