Le interrogazioni annidate

Documenti analoghi
Basi di Dati: Corso di laboratorio

Linguaggio SQL seconda parte

<Nome Tabella>.<attributo>

Operatori aggregati: COUNT

Structured Query Language

SQL - Sottointerrogazioni

Database Lezione 2. Sommario. - Progettazione di un database - Join - Valore NULL - Operatori aggregati

SQL [2] Concetti avanzati di SQL. Esempi di interrogazioni

Interrogare una base di dati: algebra relazionale e SQL. Savino Castagnozzi Giorgio Macauda Michele Meomartino Salvatore Picerno Massimiliano Sartor

SQL: Structured Query Language. T. Catarci, M. Scannapieco, Corso di Basi di Dati, A.A. 2008/2009, Sapienza Università di Roma

Tipi di sottoquery SQL

SQL quick reference. piccolo manuale di riferimento dei principali comandi SQL (prof. Claudio Maccherani, Perugia, 2013)

Manuale SQL. Manuale SQL - 1 -

Caratteristiche dei linguaggi per Database

Linguaggio SQL. studenti matricola nome cognome citta anno 11 marco bini bologna laura sicuro rimini 1984 esami codice

Data Management Software. Il linguaggio SQL. Query Innestate. Paolo Avallone Sr Consulting IT Specialist DB2, Data Management 10 Settembre 2003

Structured. Language. Basi di Dati. Introduzione. DDL: Data Definition Language. Tipi di dato. Query. Modifica dei Dati

Interrogazioni nidificate

Il linguaggio SQL: query innestate

SQL - Structured Query Language

Microsoft Access (parte 5) Query. Query. Query. Query. Creare una query

Alessandra Raffaetà. Esercizio: Cinema

S.I.T. PER LA VALUTAZIONE E GESTIONE DEL TERRITORIO Corso di Laurea Magistrale in Scienze Ambientali. Alessandra Raffaetà

Interrogazioni nidificate

Microsoft Access. Microsoft Access. Maurizio Rebaudengo, Paolo Garza 1. Microsoft Access. Creazione base di dati. Apertura di una base dati

Query. Query (Interrogazioni) SQL SQL. Significato dell interrogazione. Sintassi

Esercitazione: Interrogazioni SQL

Corso di Basi di Dati A.A. 2015/2016

Filtri. Microsoft Access. Filtri. Filtri

Il linguaggio SQL: raggruppamenti. Versione elettronica: SQLb-gruppi.pdf

MODULO 2. Query normali e parametriche Query di:

CORSO ACCESS 2000 PARTE VI

Esercitazione 3 SQL 2

Basi di Dati: Corso di laboratorio

Eprogram ITIS V anno Unità 4 - Il linguaggio SQL

Lezione 6. Algebra e Calcolo Relazionale

SQL e algebra relazionale

Estensioni del linguaggio SQL per interrogazioni OLAP

PRINCIPI DI INFORMATICA CORSO DI LAUREA IN SCIENZE BIOLOGICHE

SQL Avanzato. Interrogazioni e il valore NULL. Interrogazioni complesse, trigger, viste e modifiche dello schema. Giorgio Giacinto 2015

SELECT s.nome, e.data Studenti s, Esami e WHERE e.materia = 'BD' AND e.voto = 30 AND e.matricola = s.matricola

Basi di Dati: Corso di laboratorio

Il sistema informativo deve essere di tipo centralizzato e accessibile mediante un computer server installato nella rete locale dell albergo.

Le query di comando e di servizio in Access

Capitolo 4. SQL: il linguaggio di interrogazione. Originato da SEQUEL-XRM e System-R ( ) dell IBM

BASI DATI: algebra relazionale

ACCESS Esercitazione (query complesse) Ing. Cosimo Orlacchio

Equivalenza di Espressioni Algebriche

SQL QUERY: Le interrogazioni del database

SQL e linguaggi di programmazione. Cursori. Cursori. L interazione con l ambiente SQL può avvenire in 3 modi:

Algebra Relazionale. T. Catarci, M. Scannapieco, Corso di Basi di Dati, A.A. 2008/2009, Sapienza Università di Roma

Basi di dati 8 settembre 2015 Esame Compito A Tempo a disposizione: due ore. Libri chiusi.

Esempio di database relazionale con l utilizzo del prodotto MySQL

Sommario. Introduzione... 13

ESERCITAZIONI ACCESS

Access. P a r t e t e r z a

Interrogazioni in SQL

Basi di Dati. Esercitazione 1: Interrogazioni in SQL. K. Donno - Interrogazioni in SQL

Basi di dati I 8 luglio 2016 Esame Compito A Tempo a disposizione: un ora e trenta minuti.

Foglio Elettronico Lezione 1

ESERCITAZIONE 4 Giovedì 13 novembre 2014 (3 ore) SQL

Algebra relazionale: operazioni

DATABASE PER IL WEB. Programmazione Web 1

V. Moriggia Modelli di Base Dati. Modelli di Base Dati. a.a. 2001/

Tipi di operatori. Gli operatori dell algebra relazionale sono classificabili nelle seguenti categorie:

Transcript:

Le interrogazioni annidate Lezione 5 lezione 5 Le interrogazioni annidate In questa lezione impareremo... a codificare operazioni insiemistiche su tabelle e relazioni a eseguire interrogazioni scalari a condizionare le subquery con gli operatori di quantificazione semplice ed esistenziale Le operazioni insiemistiche In questa lezione vengono esaminate le interrogazioni nidificate. Esse rappresentano uno strumento valido per effettuare interrogazioni complesse, che non possono essere realizzate con i comandi SQL visti finora. In pratica, un interrogazione nidificata (o subquery) non è altro che un interrogazione che permette il confronto tra uno o più attributi e il risultato di una sottointerrogazione. Di seguito elenchiamo i vantaggi offerti dall uso delle subquery. Le subquery permettono interrogazioni strutturate, rendendo in tal modo possibile la separazione di ogni singola parte significativa del comando SQL. Esse rappresentano un metodo alternativo alle congiunzioni per eseguire operazioni che altrimenti renderebbero necessario l uso di queste complesse istruzioni. È opinione comune che l introduzione delle subquery sia stata l innovazione che ha consentito di definire SQL un vero e proprio linguaggio strutturato. Le operazioni insiemistiche vengono anche chiamate query binarie o set queries e permettono di combinare insieme più SELECT per ottenere un unico output. Si ottengono concatenando due query SQL tramite operatori insiemistici di unione, intersezione e differenza. La sintassi generale secondo SQL standard è la seguente: è necessario, però, osservare che sia MySQL sia Access utilizzano il solo operatore UNION, che permette di unire due tabelle mediante un campo comune. Infatti, i due operatori insiemistici INTERSECT ed EXCEPT possono essere sostituiti da interrogazioni equivalenti. Query esterna SQL { UNION INTERSECT EXCEPT [ALL] Query interna SQL } P. Camagni, R. Nikolassy, Progettare i database, Nuova Edizione OPENSCHOOL, Ulrico Hoepli Editore S.p.A. 2014 1

UdA 3 Il linguaggio SQL La funzione di unione può essere espressa mediante la figura che segue, in cui si evidenzia come la struttura possa essere ciclica, ovvero nidificata; inoltre, per ogni result-set si ottiene la somma con la successiva. Le principali caratteristiche dell operatore UNION sono indicate brevemente di seguito. L esecuzione di un insieme di più UNION (senza parentesi) avviene in ordine da sinistra verso destra. Le singole SELECT che partecipano alla UNION non possono avere loro clausole ORDER BY; un unico ORDER BY può essere specificato dopo l ultima SELECT e viene applicato al risultato finale delle operazioni di UNION. Le clausole GROUP BY e HAVING possono essere specificate per le singole clausole SELECT, ma non per il risultato finale. Mediante gli operatori insiemistici si ottiene un eliminazione dei duplicati e anche delle proiezioni, a meno che non venga usata la clausola ALL. Esempio 14 Vediamo un esempio per comprendere meglio il significato di questo operatore. Utilizziamo le due tabelle seguenti: nella prima, denominata Maternità, vi sono i nomi delle madri e dei relativi figli, mentre nella tabella Paternità vi sono i nomi dei padri e dei relativi figli. Tabella Maternità tabella Paternità La query insiemistica può essere vista come un unione basata sugli attributi esposti nella target list delle due SELECT. In pratica, vengono unite tutte le tuple delle due tabelle che hanno gli attributi uguali, sia come tipo che come ordine sequenziale. Tale ordine viene chiamato notazione posizionale. Per esempio, si vogliono conoscere tutti i nomi dei genitori e dei relativi figli mediante la seguente query: Select nome_figlio, cognome_figlio, nome_madre, cognome_madre FROM Maternità UNION Select nome_figlio, cognome_figlio, nome_padre, cognome_padre FROM Paternità 2 P. Camagni, R. Nikolassy, Progettare i database, Nuova Edizione OPENSCHOOL, Ulrico Hoepli Editore S.p.A. 2014

Le interrogazioni annidate Lezione 5 Tale interrogazione comprende da una prima query, il cui risultato viene confrontato con le tuple ottenute dalla seconda. Nelle chermate che seguono sono indicati i passaggi che vengono eseguiti per ottenere il risultato. Nel primo passaggio abbiamo il risultato della prima query, ovvero i nomi delle madri con accanto i relativi figli. Nella schermata relativa al secondo passaggio vengono indicati i record della tabella Paternità che sono il risultato della seconda query indicata dopo la clausola UNION. Primo passaggio intermedio: 2 Secondo passaggio intermedio: Per poter realizzare un unione è necessario che le due tabelle da unire possiedano lo stesso numero di colonne, e che i domini degli attributi siano uguali. L unione delle due tabelle produce una nuova tabella che contiene tutte le righe delle tabelle di partenza, escludendo le righe doppie. In questo caso non vi sono righe doppie, per cui si ottiene: P. Camagni, R. Nikolassy, Progettare i database, Nuova Edizione OPENSCHOOL, Ulrico Hoepli Editore S.p.A. 2014 3

UdA 3 Il linguaggio SQL Quali nomi vengono associati agli attributi del risultato? In realtà gli attributi risultanti possiedono il nome che è stato assegnato dalla prima query. È quindi buona regola assegnare un nome con alias ai campi risultato. Infatti, nell esempio precedente si notano alcune incongruenze: per esempio, esistono nomi di padri nella colonna nome_madre. Vediamo come riscrivere in modo più corretto la query precedente, ottenendo così i campi Alias e nome genitore al posto di cognome e nome madre: SELECT nome_figlio, cognome_figlio, nome_madre AS nome genitore, cognome_madre AS cognome genitore FROM Maternità UNION SELECT nome_figlio, cognome_figlio, nome_padre, cognome_padre FROM Paternità Poniamo di voler conoscere tutti coloro che hanno ancora almeno un genitore. Per fare questo è sufficiente ricavare un elenco di tutti i figli dalla tabella Maternità, unendolo all elenco di tutti i figli della tabella Paternità: SELECT nome_figlio, cognome_figlio FROM Maternità UNION SELECT nome_figlio, cognome_figlio FROM Paternità; Ottenendo così: Un utilizzo di tale clausola è legato alla possibilità di unire, appunto, le tuple risultanti da più query. Per esempio, se vogliamo conoscere il numero di figli complessivo per ciascun genitore, si deve ricorrere alla clasuola UNION che consente di visualizzare prima il totale dei figli dei padri e poi il totale di figli delle madri. Vediamo il codice in SQL: SELECT P.cognome_padre AS cognome, P.nome_padre AS nome, COUNT(*) AS totale figli FROM Paternità P GROUP BY P.cognome_padre, P.nome_padre UNION SELECT M.cognome_madre, M.nome_madre, COUNT(*) AS totale figli FROM Maternità M GROUP BY M.cognome_madre, M.nome_madre 4 P. Camagni, R. Nikolassy, Progettare i database, Nuova Edizione OPENSCHOOL, Ulrico Hoepli Editore S.p.A. 2014

Le interrogazioni annidate Lezione 5 Con il seguente risultato: Prova adesso! APRI IL FILE esempio17 Utilizzare le operazioni insiemistiche Applicare i raggruppamenti alle UNION Utilizzare GROUP BY e HAVING Crea una query che mostri tutti i cognomi disponibili in ordine crescente. 2 Crea una query che mostri tutti i cognomi presenti che iniziano per C o per V. Per fare questo crea quattro interrogazioni unite da UNION e all interno di alcune di esse utilizza la clausola WHERE. Crea una query che mostri tutti i nomi dei genitori (padri o madri) che hanno più di un figlio; per fare questo utilizza la clausola HAVING, che selezioni solo i gruppi di cognomi che hanno contato più di un figlio. Confronta la tua soluzione con quella contenuta nel file esempio17_solux Le query annidate di tipo scalare L opportunità di eseguire un interrogazione (query) secondo un determinato ordine temporale risulta di notevole importanza nello schema relazionale. Le subquery scalari annidate producono un result-set costituito da una sola tupla con un solo attributo, utilizzabile ovunque sia assegnabile un valore scalare singolo. Subquery scalari Le subquery scalari rendono le query dinamiche e rispondenti ai dati presenti nel database, piuttosto che a valori esplicitamente impostati nel codice. Per eseguire due query in modo annidato (una dentro l altra, per intenderci) è necessario prima di tutto conoscere la sintassi generale delle SELECT nidificate. P. Camagni, R. Nikolassy, Progettare i database, Nuova Edizione OPENSCHOOL, Ulrico Hoepli Editore S.p.A. 2014 5

UdA 3 Il linguaggio SQL Tale forma è sintetizzata dallo schema che segue, dove si evidenziano le parti che la compongono: prima la query esterna, poi l operatore relazionale e quindi la subquery o query annidata. query esterna Operatore query interna: restituisce solo un attributo SELECT... FROM... WHERE espressione =!= > <!>!< >= <= (SELECT... FROM... WHERE espressione) Il suo funzionamento è abbastanza semplice. La query che si trova tra le parentesi tonde, chiamata anche select interna o query annidata, viene eseguita per prima; quindi, sulla base del risultato ottenuto, viene eseguita l altra query, chiamata anche select esterna o query principale. È necessario inoltre ricordare che le sottointerrogazioni non possono contenere operatori insiemistici. La procedura risulterà più chiara con qualche esempio. Si vogliono conoscere i nomi delle madri che hanno figlie con lo stesso nome delle figlie di Colombo Piero. L interrogazione è quindi formata da una query interna che cerca il nome dei figli di Colombo Piero, e da una esterna che confronta il nome dei figli delle madri con quello trovato nella query più interna. Vediamo il codice SQL: SELECT cognome_madre, nome_madre FROM Maternità WHERE nome_figlio = ( SELECT nome_figlio FROM Paternità WHERE cognome_padre= Colombo and nome_padre= Piero ); Query esterna Query interna In quest altro esempio si vede come è possibile usare una query annidata per verificare quali padri hanno avuto meno figli di Corelli Lina : SELECT cognome_padre, nome_padre, COUNT(*) AS figli FROM paternità GROUP BY cognome_padre, nome_padre HAVING COUNT(*)< ( SELECT COUNT(*) FROM Maternità WHERE cognome_madre= Corelli and nome_madre= Lina ); L operazione di nidificazione può anche essere effettuata in riferimento a differenti condizioni nella stessa query. A questo proposito, vediamo un altro esempio: si vuole conoscere il nome e cognome della nonna da parte di padre di Valli Mario. Per fare questo è sufficiente selezionare il nome del padre di Valli Mario in una query interna. La query più esterna cerca nella tabella Maternità la madre che ha nome e cognome del figlio uguali a quelli risultati dalla query più interna. L aspetto problematico deriva dal fatto che la query più esterna deve confrontare due attributi, il cognome e il nome. In tal caso è necessario scrivere due query interne: la prima viene confrontata con il cognome, mentre la seconda con il nome. Per migliorarne la leggibilità è consigliabile indentare le query più interne. 6 P. Camagni, R. Nikolassy, Progettare i database, Nuova Edizione OPENSCHOOL, Ulrico Hoepli Editore S.p.A. 2014

Le interrogazioni annidate Lezione 5 Vediamo il codice: SELECT cognome_madre AS cognome nonna, nome_madre AS nome nonna FROM Maternità WHERE cognome_figlio= ( SELECT cognome_padre FROM Paternità WHERE cognome_figlio= Valli and nome_figlio= Mario ) and nome_figlio= ( SELECT nome_padre FROM Paternità WHERE cognome_figlio= Valli and nome_figlio= Mario ); Esempio 15 In questo esempio abbiamo una base di dati formata da due tabelle: Dipendenti e Mansioni. Per ciascun dipendente è associata una mansione. Tale mansione è presente in una tabella separata, chiamata appunto Mansioni, che è in relazione 1 a N con la tabella Dipendenti. Vediamo di seguito i dati contenuti nelle due tabelle. Tabella Dipendenti tabella Mansioni Se volessimo conoscere il cognome e il nome di tutti i dipendenti che hanno stipendio inferiore alla media di quelli con mansione 9, ma superiore alla media di quelli con mansione 10, dovremmo applicare le conoscenze acquisite in campo di condizioni multiple, viste nell esempio precedente: SELECT cognome, nome, stipendio FROM Dipendenti WHERE stipendio < (SELECT AVG(stipendio) FROM Dipendenti WHERE mansione=9) and stipendio > (SELECT AVG(stipendio) FROM Dipendenti WHERE mansione=10) Si ottiene: P. Camagni, R. Nikolassy, Progettare i database, Nuova Edizione OPENSCHOOL, Ulrico Hoepli Editore S.p.A. 2014 7

UdA 3 Il linguaggio SQL Query annidate e join Anche in questo caso utilizziamo il database dell esempio 18. Supponiamo di voler ottenere la denominazione delle mansioni e i nominativi dei dipendenti che hanno stipendio superiore alla media. Allo scopo di facilitare la comprensione della query, sono necessarie alcune considerazioni. La ricerca dell attributo della mansione, in questo esempio, associato a un valore calcolato con un operatore di aggregazione (AVG), si può ottenere mediante nidificazione, in modo analogo agli esempi fin qui trattati. Per poter rispondere al quesito, però, è necessario considerare che i dati utili a una delle due SELECT si trovano su tabelle separate, quindi si deve ricorrere anche a una congiunzione (join). La soluzione al quesito viene esposta suddividendo le tre query e valutandone i risultati separatamente. La prima query calcola la media dello stipendio della tabella Dipendenti. SELECT AVG(stipendio) FROM Dipendenti La query seguente invece, mediante l uso di una join, calcola la media degli stipendi, suddivisi per mansione mediante la clausola GROUP BY: SELECT M.nome, AVG(D.stipendio) AS media FROM Mansioni M INNER JOIN Dipendenti D ON D.mansione=M.ID_mansione GROUP BY M.nome Tale query produce un elenco di tuple, contraddistinte dal nome della mansione e dalla media di stipendio calcolata per ciascuna di esse, sempre che vi siano dipendenti per quella mansione, visto che è stata usata una inner join: Per conoscere invece quali mansioni hanno una media di stipendio superiore alla media complessiva è necessario annidare la query vista all inizio. Infine, utilizzando la clausola HAVING è possibile stabilire una condizione sull attributo media delle tuple sopra indicate. Vediamo il codice completo e il risultato: SELECT M.nome, AVG(D.stipendio) AS media FROM Mansioni M INNER JOIN Dipendenti D ON D.mansione=M.ID_mansione GROUP BY M.nome HAVING AVG(D.stipendio) > (SELECT AVG(stipendio) FROM Dipendenti) Le considerazioni svolte precedentemente sulle tre query e il risultato ottenuto con la figura indicata sopra possono così riassumersi: il raccordo tra le due SELECT, quella interna e quella esterna, è stato ottenuto imponendo una condizione sul raggruppamento mediante clausola HAVING nell interrogazione esterna. 8 P. Camagni, R. Nikolassy, Progettare i database, Nuova Edizione OPENSCHOOL, Ulrico Hoepli Editore S.p.A. 2014

Le interrogazioni annidate Lezione 5 Vediamo un altro esempio su come utilizzare le join all interno di query annidate. In realtà è molto semplice, in quanto abbiamo visto che ciascuna query, anche se annidata, produce una tupla risultato che viene poi confrontata con quelle prodotte dalla query più esterna. In questo ulteriore esempio si vogliono conoscere i nomi dei dipendenti che guadagnano più del Top manager; per fare questo si utilizza una congiunzione interna (inner join) tra le tabelle Dipendenti e Mansioni mediante il campo ID_mansione: SELECT matricola, cognome, nome, stipendio FROM Dipendenti WHERE stipendio > (SELECT stipendio FROM (Dipendenti D INNER JOIN Mansioni M ON D.mansione=M.ID_mansione) WHERE M.nome= top manager ); Ottenendo le seguenti tuple risultato: Una proprietà notevole delle query annidate è quella di essere equivalenti, in alcuni casi, alle self join. Per esempio, la query di cui sopra avrebbe potuto essere scritta mediante una self join come segue: SELECT D1.matricola, D1.cognome, D1.nome, D1.stipendio FROM Dipendenti D1, dipendenti D2, Mansioni M WHERE D1.stipendio > D2.stipendio and D2.mansione=M.ID_mansione and M.nome= top manager ; Ottenendo il medesimo risultato! Nel caso in cui le tuple risultanti dalla query interna siano più di una, il DBMS fornisce un messaggio di errore inequivocabile, che significa che la query interna ha restituito più diuna riga, rendendo così di fatto impossibile il confronto con un attributo della query esterna: Zoom su... Le subquery Con operatori aggregati Sempre riguardo al database dell esempio 18 vogliamo risolvere il problema seguente: vogliamo conoscere il nome dei dipendenti che guadagnano più della media di tutti i dipendenti. Escludendo il ricorso a interrogazioni che elenchino l attributo nome insieme a una funzione di gruppo, escluso qualunque raggruppamento di tuple, si eseguono due query distinte. Mediante la prima si calcola la media degli stipendi: SELECT AVG(stipendio) FROM Dipendenti; P. Camagni, R. Nikolassy, Progettare i database, Nuova Edizione OPENSCHOOL, Ulrico Hoepli Editore S.p.A. 2014 9

uda 3 Il linguaggio SQL viene utilizzato come elemento di confronto per la query più esterna, il cui codice è: SELECT cognome, nome FROM Dipendenti WHERE stipendio > 2435,56; Il difetto riscontrabile in questo tipo di approccio è legato alla non generalizzazione della seconda query, in quanto una variazione dei dati della tabella Dipendenti comporta anche una sua modifica. La nidificazione delle query evita questo inconveniente per la modifica della condizione stabilita nell esempio citato sopra. Si tratta di unire le query precedenti, legandole mediante un operatore di confronto (>): SELECT cognome, nome FROM Dipendenti WHERE stipendio > (SELECT AVG(stipendio) FROM Dipendenti); Ottenendo così: In questo esempio abbiamo visto come esprimere, mediante la nidificazione, espressioni condizionali in cui si confronta uno scalare con un valore restituito da un operatore aggregato. Prova adesso! Applicare le subquery Utilizzare i raggruppamenti nelle subquery APRI IL FILE esempio18 Si vogliono conoscere i nomi, la mansione e la paga oraria dei dipendenti che hanno stipendio superiore a quello dell autista che guadagna di più. Ti consiglio di calcolare innanzitutto lo stipendio massimo degli autisti come dato scalare nella subquery, quindi nella query più esterna ricerca tutti quei dipendenti che hanno stipendio superiore a 1650. 2 Confronta la tua soluzione con quella contenuta nel file esempio18_solux. Condizioni su valori non scalari con i quantificatori ALL, ANY e SOME Una delle caratteristiche innovative di SQL fu quella di rendere possibile l effettuazione di query annidate in grado di confrontare più valori restituiti dalla query più interna. Finora abbiamo ipotizzato che la query interna generasse sempre valori scalari, cioè unici sia come numero di tuple che come attributi. In questo paragrafo ci occupiamo di confrontare su un unico attributo valori non scalari, cioè liste di valori. 10 P. Camagni, R. Nikolassy, Progettare i database, Nuova Edizione OPENSCHOOL, Ulrico Hoepli Editore S.p.A. 2014

Le interrogazioni annidate Lezione 5 Le clausole ALL, ANY e SOME rendono possibile il confronto tra un attributo e un insieme di valori. Per comprenderne il meccanismo di funzionamento svilupperemo un esempio. Supponiamo di voler conoscere i nomi dei dipendenti che guadagnano meno di 1500 euro con la stessa mansione di quelli che ne guadagnano di più. Il risultato si ottiene calcolando, con una nidificazione, le tipologie di mansione dei dipendenti che guadagnano meno di 1500 euro, confrontate con le mansioni di coloro che guadagnano più di 1500 euro. Purtroppo la query seguente è errata: SELECT cognome, nome, stipendio FROM Dipendenti WHERE stipendio <=1500 AND mansione = (SELECT mansione FROM Dipendenti WHERE stipendio>1500); La subquery, infatti, ha cardinalità maggiore di uno, quindi il confronto non può essere valido. Questo si verifica in quanto la condizione tra le due query è di tipo ambiguo : questa, infatti, deve valere per uno o per tutti gli scalari calcolati dall interrogazione interna? La specificazione di una delle tre clausole ALL/ANY/SOME risolve l ambiguità, in quanto permette di definire un set di valori. Esaminiamo meglio queste clausole. ALL signica che la condizione deve essere valida per una qualsiasi tupla del risult-set interno; SOME è equivalente a ad ANY, ed è stato introdotto in MySQL per correttezza linguistica; ALL identifica tutte le tuple della relazione più interna. Vediamo ora come applicarle nella query vista sopra, correggendo in tal modo l errore sul confronto: SELECT cognome, nome, stipendio FROM Dipendenti WHERE stipendio <=1500 AND mansione = ANY (SELECT mansione FROM Dipendenti WHERE stipendio>1500); La query deve essere letta in questo modo: elencare tutti i dipendenti che hanno stipendio minore o uguale a 1500 con mansione uguale a uno qualsiasi tra i dipendenti con la stessa mansione ma con stipendio maggiore di 1500. Vediamo il risultato ottenuto: La prossima query mostra con un esempio quando ricorrere alla clausola ALL. Si vuole conoscere il nome e la mansione dei dipendenti con uno stipendio più alto di quello di tutti i dipendenti con mansione autista. P. Camagni, R. Nikolassy, Progettare i database, Nuova Edizione OPENSCHOOL, Ulrico Hoepli Editore S.p.A. 2014 11

UdA 3 Il linguaggio SQL In questo caso, è la stessa espressione maggiore di tutti a facilitare la comprensione della clausola di relazione con la subquery, che riportiamo di seguito insieme al risultato ottenuto: SELECT M.nome AS mansione, D.cognome, D.nome, D.stipendio FROM Dipendenti D INNER JOIN Mansioni M ON M.ID_mansione=D.mansione WHERE D.stipendio > ALL (SELECT D.stipendio FROM Dipendenti D, Mansioni M WHERE M.nome= autista and M.ID_mansione=D.mansione) Oppure ancora, nell esempio che segue si vogliono elencare tutti i dipendenti che hanno la paga oraria superiore alla media della paga oraria degli impiegati di primo, secondo e terzo livello. Per fare questo si calcola la media della paga oraria riferita agli impiegati (mediante LIKE), quindi la query esterna ricerca tutte le mansioni, con il relativo dipendente con paga oraria maggiore del risultato della subquery interna. Vediamo la codifica, prima per MySQL: SELECT M.nome AS mansione, D.cognome, D.nome, M.tariffa_oraria FROM Dipendenti D INNER JOIN Mansioni M ON M.ID_mansione=D.mansione WHERE M.tariffa_oraria > ALL (SELECT AVG(tariffa_oraria) FROM Mansioni WHERE nome LIKE impiegato% ) Ottenendo: Si ricorda Esistono che delle il carattere corrispondenze jolly %, tra in alcune Access clausole è sostituito di aggregazione. dal carattere Per *. esempio, la clausola (= ANY) è del tutto equivalente a (IN), mentre (<> ALL) è del tutto equivalente a (NOT IN). La quantificazione esistenziale La quantificazione esistenziale permette di verificare l esistenza di almeno una tupla nel result-set della subquery. La proiezione restituita dalla subquery è assolutamente irrilevante, quindi può essere opportuno indicare sempre una proiezione di tipo star (*). La sua sintassi è la seguente: SELECT attributo1 FROM tabella1 WHERE [NOT] EXISTS (SELECT * FROM tabella2); 12 P. Camagni, R. Nikolassy, Progettare i database, Nuova Edizione OPENSCHOOL, Ulrico Hoepli Editore S.p.A. 2014

Le interrogazioni annidate Lezione 5 Se una subquery restituisce almeno una tupla, EXISTS fornisce un valore True, altrimenti avrà un valore False. Come si può notare, se la tabella 2 contiene almeno una riga, la condizione WHERE della query esterna è True. Esempio 16 In questo esempio utilizziamo come esempio le tabelle che seguono. Tabella Studenti Tabella Esami Vogliamo conoscere l elenco degli studenti che non hanno superato alcun esame. Per fare questo, si crea un interrogazione esterna che elenca tutti gli studenti con proiezione sui dati anagrafici, mentre la congiunzione prevede l uso del quantificatore esistenziale negato con NOT, che significa non esiste nemmeno una tupla nella subquery. In questo esempio è stata usata la correlazione per legare tra loro le tabelle Studenti (nella query esterna) con Esami. SELECT ID_studente,cognome, nome FROM Studenti S WHERE NOT EXISTS (SELECT * FROM Esami WHERE S.ID_studente=id_Studente) Per verificare, invece, quali sono gli studenti che hanno sostenuto almeno un esame, si utilizza il quantificatore EXISTS. Vediamone la codifica e il risultato: SELECT ID_studente,cognome, nome FROM Studenti S WHERE EXISTS (SELECT * FROM Esami WHERE S.ID_studente=id_Studente) P. Camagni, R. Nikolassy, Progettare i database, Nuova Edizione OPENSCHOOL, Ulrico Hoepli Editore S.p.A. 2014 13

uda 3 Il linguaggio SQL Verifichiamo le conoscenze g Esercizi a scelta multipla 1 Quale dei seguenti non è un operatore insiemistico di SQL? a) UNION b) INTERSECT c) POWERSET d) EXCEPT 2 In SQL, volendo dividere le righe di una tabella in insiemi caratterizzati dallo stesso valore degli attribuiti che compaiono come argomento, si usa l operatore: a) ORDER BY b) GROUP BY c) SELECT BY 3 Dato il seguente schema relazionale: Ordini(ID_ord, articolo, cliente, data, quantità, id_venditore) Venditori(ID_venditore, nome, qualifica) indica quale tra le seguenti query rappresenta i nomi dei venditori che non hanno ancora venduto nulla nell anno 2006. a) SELECT V.NOME FROM Venditori V WHERE NOT EXISTS (SELECT * FROM Ordini O WHERE O.id_venditore=V.ID_venditori AND year(o.data)= 2006 ) b) SELECT * FROM Venditori V WHERE NOT IN (SELECT * FROM Ordini O WHERE O.id_venditore=V.ID_venditori AND year(o.data)= 2006 ) c) SELECT V.nome FROM Venditori V WHERE EXISTS (SELECT DISTINCT * FROM Ordini O WHERE O.id_venditore=V.ID_venditori AND year(o.data)= 2006 ) d) SELECT V.nome FROM Venditori V WHERE year(o.data)=2006 and NOT EXISTS (SELECT * FROM Venditori V INNER JOIN Ordini O ON O.id_venditore=V.ID_venditori) 3 Indica a quale categoria appartiene la seguente query: SELECT cognome, nome FROM Amici WHERE nome= (SELECT nome FROM Amici WHERE cognome= Verdini and nome= Pio ); a) query derivata b) query correlata c) subquery d) query scalare 4 Indica a quale categoria appartiene la seguente query: SELECT cognome, nome, stipendio FROM Amici WHERE stipendio < 14 P. Camagni, R. Nikolassy, Progettare i database, Nuova Edizione OPENSCHOOL, Ulrico Hoepli Editore S.p.A. 2014

Le interrogazioni annidate Lezione 5 (SELECT MAX(stipendio) FROM Amici) a) query insiemistica b) query calcolata c) query scalare d) query correlata g Test vero/falso 1 Le clausole HAVING e GROUP BY possono essere specificate per il risultato finale di una UNION. 2 È possibile ottenere query multiple unite con UNION. g Esercizi 1 Illustra come avviene l operazione di UNION tra due query. 2 Perché è di norma utile assegnare un nome come alias agli attributi risultato della prima query di una UNION? 3 Individua l errore nella seguente query annidata: SELECT * FROM Correntisti C WHERE CC.cognome<> (SELECT cognome FROM ContiCorrenti CC WHERE year(data)>1986); 4 Riscrivi la seguente query utilizzando le tecniche di annidamento corrette: SELECT D.cognome, D.nome, D.stipendio FROM Impiegati D INNER JOIN Impiegati D1 ON D.ID_superiore=D1.ID_impiegato WHERE D.stipendio>D1.stipendio 5 Riscrivi la seguente query utilizzando le tecniche di annidamento corrette: SELECT cognome, nome, stipendio FROM Dipendenti D, Aziende A WHERE D.id_azienda=A.ID_azienda and A.nome= FIAT ; 6 Riscrivi la seguente query senza utilizzare le tecniche di annidamento, con e senza l uso della congiunzione: SELECT * FROM Clienti WHERE cognome =ANY (SELECT cognome FROM Appuntamenti WHERE id_trattamento=any (SELECT ID_trattamento FROM Trattamenti WHERE descrizione LIKE %lamp% )); P. Camagni, R. Nikolassy, Progettare i database, Nuova Edizione OPENSCHOOL, Ulrico Hoepli Editore S.p.A. 2014 15

uda 3 Il linguaggio SQL Verifichiamo le competenze g Problemi 1 Considera una tabella a piacere contenente un attributo di valori numerici qualsiasi. Si chiede di scrivere la query che calcola il dato immediatamente superiore al minimo per quell attributo. 2 Dato lo schema relazionale costituito dalle seguenti tabelle: Persone(nome, reddito, età, sesso, indirizzo, città) Genitori_figli(ID, nome_genitore, nome_figlio, ordine_figlio) esprimi in SQL le seguenti interrogazioni: a) Trovare l elenco ordinato dei genitori i cui figli guadagnano tutti più di 10.000 b) Elencare per ogni persona l età media dei suoi figli c) Elencare i figli la cui età è maggiore della media delle età dei figli dello stesso genitore d) Elencare per ogni persona il primo figlio e) Elencare i genitori senza figli 3 Dato lo schema relazionale costituito dalle seguenti tabelle: Pilota Pilota (ID_pilota, nome, cognome, num_mondiali_vinti, nazione) Gara (ID_gara, nome, data, id_vincitore) esprimi in SQL le seguenti interrogazioni: a) Elencare i nomi dei piloti che, a partire dal 1970, hanno vinto almeno 2 gare b) Elencare il nome di tutti i piloti che hanno vinto almeno un mondiale ma non hanno mai vinto il Gran Premio di San Marino c) Elencare quale pilota ha vinto più GP del Brasile d) Elencare quali piloti non hanno mai vinto alcun mondiale pur avendo vinto almeno una gara e) Elencare il pilota italiano che ha vinto più gare della media di tutti i piloti tedeschi 4 Dato lo schema relazionale costituito dalle seguenti tabelle: Programma(ID_programma, nome, tipo, durata) Orario(canale_tv, data, ora, minuti, id_programma) esprimi in SQL le seguenti interrogazioni: a) Elencare i canali televisivi che non hanno mai trasmesso programmi di tipo intrattenimento con durata inferiore a 20 minuti nel periodo dal 20/12/2006 al 05/01/2005 b) Elencare il codice, nome, e il canale di programmazione, data e ora di inizio dei relativi programmi di tipo sport, trasmessi da più di 2 canali televisivi diversi c) Elencare quali canali televisivi hanno trasmesso, nel periodo gennaio 2005, almeno un programma di genere sport ma nessun programma di cultura d) Elencare i programmi televisivi con durata inferiore alla media di quelli sportivi e superiore a quella del programma culturale più lungo 16 P. Camagni, R. Nikolassy, Progettare i database, Nuova Edizione OPENSCHOOL, Ulrico Hoepli Editore S.p.A. 2014