Sottoquery (SQL Server)

  • 18/02/2018
  • 21 minuti per leggere
    • W
    • M
    • T
    • M
    • j
    • +3

Si applica a: SQL Server (tutte le versioni supportate) Database SQL di Azure Istanza gestita di Azure SQL Azure Synapse Analytics Parallel Data Warehouse

Una sottoquery è una query nidificata all’interno di un SELECT, INSERT, UPDATE o DELETE o all’interno di un’altra sottoquery. Una sottoquery può essere utilizzata ovunque sia consentita un’espressione. In questo esempio, una sottoquery viene utilizzata come espressione di colonna denominata MaxUnitPrice in un’istruzione SELECT.

Fondamenti di sottoquery

Una sottoquery è anche chiamata query interna o selezione interna, mentre l’istruzione contenente una sottoquery è anche chiamata query esterna o selezione esterna.

Molte istruzioni Transact-SQL che includono sottoquery possono essere formulate in alternativa come join. Altre domande possono essere poste solo con sottoquery. In Transact-SQL, di solito non c’è differenza di prestazioni tra un’istruzione che include una sottoquery e una versione semanticamente equivalente che non lo fa. Tuttavia, in alcuni casi in cui è necessario verificare l’esistenza, un join produce prestazioni migliori. In caso contrario, la query nidificata deve essere elaborata per ogni risultato della query esterna per garantire l’eliminazione dei duplicati. In questi casi, un approccio di join produrrebbe risultati migliori. Il seguente è un esempio che mostra sia una sottoquery SELECT e un join SELECT che restituiscono lo stesso set di risultati:

Una sottoquery nidificata nell’istruzione SELECT esterna ha i seguenti componenti:

  • Una query SELECT regolare inclusi i normali componenti dell’elenco di selezione.
  • Una clausola FROM che include uno o più nomi di tabelle o viste.
  • Un WHERE clausola.
  • Una GROUP BY clausola facoltativa.
  • Una HAVING clausola.

La query SELECT di una sottoquery è sempre racchiusa tra parentesi. Non può includere una clausola COMPUTE o FOR BROWSE e può includere una clausola ORDER BY quando viene specificata anche una clausola TOP.

Una sottoquery può essere nidificata all’interno della clausola WHERE o HAVING di una clausola esterna SELECT, INSERT, UPDATE o DELETE istruzione o all’interno di un’altra sottoquery. È possibile un massimo di 32 livelli di nidificazione, sebbene il limite vari in base alla memoria disponibile e alla complessità di altre espressioni nella query. Le singole query potrebbero non supportare la nidificazione fino a 32 livelli. Una sottoquery può apparire ovunque sia possibile utilizzare un’espressione, se restituisce un singolo valore.

Se una tabella appare solo in una sottoquery e non nella query esterna, le colonne di tale tabella non possono essere incluse nella output (l’elenco di selezione della query esterna).

Le dichiarazioni che includono una sottoquery di solito accettano uno di questi formati:

  • WHERE espressione IN (sottoquery)
  • WHERE espressione confronto_operator (subquery)
  • WHERE EXISTS (subquery)

In alcune istruzioni Transact-SQL, la sottoquery può essere valutata come se fosse query. Concettualmente, i risultati delle sottoquery vengono sostituiti nella query esterna (sebbene questo non sia necessariamente il modo in cui SQL Server elabora effettivamente le istruzioni Transact-SQL con le sottoquery).

Esistono tre tipi di base di sottoquery. Quelli che:

  • Operano su elenchi introdotti con IN o quelli che un operatore di confronto ha modificato da ANY o ALL.
  • Vengono introdotti con un operatore di confronto non modificato e devono restituire un singolo valore.
  • I test di esistenza sono introdotti con EXISTS.

Regole di sottoquery

Una sottoquery è soggetta alle seguenti limitazioni:

  • L’elenco di selezione di una sottoquery introdotta con un operatore di confronto può includere solo un’espressione o un nome di colonna (tranne per il fatto che EXISTS e IN operano su SELECT * o un elenco, rispettivamente).
  • Se la clausola WHERE di una query esterna include un nome di colonna, deve essere compatibile con il join con la colonna nell’elenco di selezione delle sottoquery.
  • I tipi di dati ntext, text e image non possono essere utilizzati nell’elenco di selezione delle sottoquery.
  • Poiché devono restituire un singolo valore, le sottoquery introdotte da un operatore di confronto non modificato (uno non seguito dalla parola chiave ANY o ALL) non può includere le clausole GROUP BY e HAVING.
  • Le clausole DISTINCT non può essere utilizzata con sottoquery che includono GROUP BY.
  • COMPUTE e INTO non possono essere specificate.
  • ORDER BY può essere specificato solo quando è specificato anche TOP.
  • Non è possibile aggiornare una vista creata utilizzando una sottoquery.
  • L’elenco di selezione di una sottoquery introdotto con EXISTS, per convenzione, ha un asterisco ( *) invece del nome di una singola colonna. Le regole per una sottoquery introdotta con EXISTS sono le stesse di un elenco di selezione standard, perché una sottoquery introdotta con EXISTS crea un’esistenza test e restituisce TRUE o FALSE, invece di dati.

Nomi di colonna qualificati nelle sottoquery

Nell’esempio seguente, la colonna BusinessEntityID in della query esterna è qualificata implicitamente dal nome della tabella nella clausola FROM della query esterna (Sales.Store). Il riferimento a CustomerID nell’elenco di selezione della sottoquery è qualificato dalla sottoquery FROM clausola, ovvero dalla tabella Sales.Customer.

La regola generale è che i nomi di colonna in un’istruzione sono qualificati implicitamente dalla tabella a cui si fa riferimento nella clausola FROM allo stesso livello. Se una colonna non esiste nella tabella a cui si fa riferimento nella clausola FROM di una sottoquery, viene implicitamente qualificata dalla tabella a cui si fa riferimento nel FROM clausola della query esterna.

Ecco come appare la query con questi presupposti impliciti specificati:

Non è mai sbagliato per dichiarare esplicitamente il nome della tabella ed è sempre possibile sovrascrivere i presupposti impliciti sui nomi delle tabelle con qualifiche esplicite.

Importante

Se si fa riferimento a una colonna in una sottoquery che non esiste nella tabella a cui fa riferimento la sottoquery “s FROM clausola, ma esiste in una tabella a cui fa riferimento la query esterna” s FROM clausola, la query viene eseguita senza errori. SQL Server qualifica implicitamente la colonna nella sottoquery con il nome della tabella nella query esterna.

Più livelli di nidificazione

Una sottoquery può essa stessa includere una o più sottoquery. Qualsiasi numero di sottoquery può essere annidato in un’istruzione.

La seguente query trova i nomi dei dipendenti che sono anche addetti alle vendite.

Ecco il set di risultati.

La query più interna restituisce gli ID del venditore. La query al livello superiore successivo viene valutata con questi ID addetto alle vendite e restituisce i numeri ID di contatto dei dipendenti. Infine, la query esterna utilizza gli ID contatto per trovare i nomi dei dipendenti.

Puoi anche esprimere questa query come un join:

Molte query possono essere valutate eseguendo la sottoquery una volta e sostituendo il valore oi valori risultanti nella clausola WHERE della query esterna. Nelle query che includono una sottoquery correlata (nota anche come sottoquery ripetuta), la sottoquery dipende dalla query esterna per i suoi valori. Ciò significa che la sottoquery viene eseguita ripetutamente, una volta per ogni riga che potrebbe essere selezionata dalla query esterna. Questa query recupera un’istanza del nome e del cognome di ciascun dipendente per il quale il bonus nella tabella SalesPerson è 5000 e per il quale il i numeri di identificazione dei dipendenti corrispondono nelle tabelle Employee e SalesPerson.

Ecco il set di risultati.

La sottoquery precedente in questa istruzione non può essere valutata indipendentemente dalla query esterna. È necessario un valore per Employee.BusinessEntityID, ma questo valore cambia quando SQL Server esamina righe diverse in Employee.
È esattamente così la query viene valutata: SQL Server considera ogni riga della tabella Employee per l’inclusione nei risultati sostituendo il valore in ciascuna riga nella query interna. Ad esempio, se SQL Server esamina prima la riga per Syed Abbas, la variabile Employee.BusinessEntityID assume il valore 285, che SQL Server sostituisce utes nella query interna.

Il risultato è 0 (Syed Abbas non ha ricevuto un bonus perché è non un venditore), quindi la query esterna restituisce:

Poiché questo è falso, la riga per Syed Abbas non è incluso nei risultati.

Write a Comment

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *