Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Subquery

Come utilizzare le possibili tipologie di subquery supportate su SQL, insieme ad una panoramica delle parole chiave IN, SOME, ANY, ALL ed EXISTS.
Come utilizzare le possibili tipologie di subquery supportate su SQL, insieme ad una panoramica delle parole chiave IN, SOME, ANY, ALL ed EXISTS.
Link copiato negli appunti

Nelle precedenti lezioni abbiamo visto come eseguire le principali operazione su un database relazionale tramite SQL, descrivendo il funzionamento e la sintassi delle istruzioni INSERT, SELECT, UPDATE e DELETE. Alcune situazioni più complesse, inoltre, possono essere gestite sfruttando le cosiddette subquery, cioè inserendo l'istruzione SELECT all'interno di query che ne contengono già una, o che contengono altre istruzioni come le precedenti.

Nella lezione sull'istruzione UPDATE, abbiamo già visto un esempio di subquery, che riportiamo qui di seguito:

UPDATE Book SET note= 'editore: ' + (SELECT name FROM Publisher WHERE Publisher.ID = Book.publisher)

In questo caso, all'interno di una query di modifica dei dati, abbiamo avuto bisogno di selezionare una serie di record sfruttando un'intera query di selezione.

Di seguito approfondiremo più nel dettaglio come e quando ha senso l'uso di una subquery, con alcuni esempi pratici di utilizzo.

Operazioni su subquery

Per capire in che modo utilizzare una subquery, è necessario innanzitutto soffermarsi sui possibili valori di ritorno di una query di selezione (ovvero di una query che utilizza l'istruzione SELECT). Lo faremo sfruttando alcuni esempi, ognuno dei quali utilizza un diverso tipo di subquery, e che ci porterà a discutere alcuni costrutti interessanti del linguaggio SQL.

La parola chiave IN

Iniziamo con la query seguente:

SELECT *
FROM Clienti
WHERE id IN (SELECT idCliente
             FROM Incassi
             WHERE importo > 1000)

La subquery interna ritorna un insieme di id di clienti, e più precisamente quelli per i quali il campo importo supera il valore 1000. Se osserviamo ora l'intera query, noteremo la parola chiave IN: dal momento che è inserito all'interno di una clausola WHERE, questo costrutto ci permette di selezionare tutte e sole le righe della tabella Clienti tali che il campo id sia presente tra i risultati della subquery. Utilizzando NOT IN otterremmo, ovviamente, l'esatto contrario: selezioneremmo tutti quei clienti il cui id NON è presente tra i risultati della subquery.

Le parole chiave SOME, ANY ed ALL

Altre possibilità offerte da SQL sono rappresentate dalle parole chiave SOME, ANY ed ALL. Immaginiamo di volere selezionare una riga della tabella Incassi solo se la colonna importo è maggiore di almeno uno dei valori ritornati da una subquery. Possiamo implementare questa logica con la parola chiave SOME (nonchè con la parola chiave ANY, che è in tutto e per tutto equivalente):

SELECT *
FROM Incassi
WHERE importo > SOME (SELECT costo
                      FROM Commesse
                      WHERE tipologia = 'commessaSemplice')

Modificare il funzionamento di un operatore di confronto come > ci permette di verificare se un valore di un campo (in questo caso importo) è maggiore di almeno uno degli elementi di un insieme di valori (ovvero il risultato della subquery).

Modifichiamo ora la precedente query utilizzando la parola chiave ALL al posto di SOME:

SELECT *
FROM Incassi
WHERE importo > ALL (SELECT costo
                      FROM Commesse
                      WHERE tipologia = 'commessaSemplice')

Con ALL ci assicureremo che il valore di importo sia maggiore di tutti i valori contenuti nell'insieme dei risultati ritornato dalla subquery.

EXISTS e NOT EXISTS

In stretta correlazione con gli operatori IN e NOT IN ci sono anche EXISTS e NOT EXISTS: essi permettono, infatti, di verificare se una subquery ritorna una o più righe, ovvero se essa produce un risultato vuoto. La parola chiave EXISTS, in particolare, ritornerà un valore booleano pari a TRUE se e solo se la subquery successiva seleziona almeno una riga. Vediamo un esempio:

SELECT DISTINCT idCitta
FROM Citta
WHERE EXISTS (SELECT *
              FROM Citta_SquadreCalcio
              WHERE Citta.idCitta = Citta_SquadreCalcio.idCitta)

La query, come si evince, ritorna gli id delle città per le quali esiste almeno una squadra di calcio all'interno della tabella Citta_SquadreCalcio.

Mentre l'uso di EXISTS è facilmente comprensibile, ciò che può risultare meno intuitivo è il modo in cui la subquery è correlata con la query principale: all'interno della clausola WHERE, infatti, abbiamo utilizzato il campo idCitta della tabella Citta. Ciò implica che la subquery dovrà essere eseguita con un parametro diverso per ogni riga estratta dalla query esterna. Il risvolto pratico è un significato degrado delle prestazioni: in questi casi è sempre meglio preferire soluzioni alternative, considerato anche che spesso le subquery correlate possono essere trasformate in operazioni di JOIN o simili. Lo stesso risultato della query precedente, ad esempio, si poteva ottenere come segue:

SELECT DISTINCT idCitta
FROM Citta, Citta_SquadreCalcio
WHERE Citta.idCitta = Citta_SquadreCalcio.idCitta

Subquery e funzioni di aggregazione

Un altro possibile uso delle subquery è esemplificabile come segue:

SELECT *
FROM Studenti
WHERE voto > (SELECT AVG(voto)
              FROM Studenti)

In questo caso, e a differenza di quanto visto finora, la subquery non ritorna una serie di risultati, bensì esattamente un valore (in questo caso la media dei voti di un insieme di studenti). È quindi chiaro in che modo è possibile utilizzare una subquery che sfrutta una funzione di aggregazione (in questo caso AVG) all'interno di una clausola WHERE.

Subquery all'interno di FROM

Per concludere questa lezione, osserviamo che tutte le subquery viste finora sono state utilizzate, con gli opportuni operatori, all'interno di una clausola WHERE, per lo più in qualità di operandi su operazioni di confronto.

È altresì possibile prevedere l'uso delle subquery all'interno di una clausola FROM, indipendentemente dal fatto che essa faccia parte di una query di selezione (SELECT) piuttosto che di eliminazione (DELETE), inserimento (INSERT) o aggiornamento (UPDATE). Consideriamo l'esempio che segue:

UPDATE Tabella1
SET colonna1 = T.colonna1
FROM (SELECT *
      FROM Tabella2) AS SubQuery
INNER JOIN Tabella1 ON Tabella1.colonnaX = SubQuery.colonnaY

In questa operazione di UPDATE abbiamo effettuato un INNER JOIN tra la Tabella1 ed il risultato di una subquery: il contenuto ritornato dalla subquery è utilizzato come una vera e propria tabella, all'interno della clausola FROM. L'unica accortezza che diventa necessaria in questi casi è la necessità di utilizzare la parola chiave AS per dare un nome temporaneo al risultato della subquery (e poterne quindi richiamare i campi all'interno delle clausole WHERE o per effettuare un JOIN).

Ti consigliamo anche