Nozioni fondamentali sulle sottoquery
Una subquery è una query nidificata in un'istruzione SELECT, INSERT, UPDATE o DELETE o in un'altra subquery. È possibile utilizzare una subquery in qualsiasi posizione in cui è consentito inserire un'espressione. In questo esempio una subquery viene utilizzata come espressione di colonna MaxUnitPrice in un'istruzione SELECT.
USE AdventureWorks;
GO
SELECT Ord.SalesOrderID, Ord.OrderDate,
(SELECT MAX(OrdDet.UnitPrice)
FROM AdventureWorks.Sales.SalesOrderDetail AS OrdDet
WHERE Ord.SalesOrderID = OrdDet.SalesOrderID) AS MaxUnitPrice
FROM AdventureWorks.Sales.SalesOrderHeader AS Ord
Le subquery sono dette anche query interne o istruzioni SELECT interne. L'istruzione che include una subquery è detta anche query esterna o istruzione SELECT esterna.
Molte istruzioni Transact-SQL che includono subquery possono essere formulate anche come join. Altre domande possono essere poste solo in forma di subquery. In Transact-SQL non si rileva in genere alcuna differenza nelle prestazioni tra un'istruzione che include una subquery e una versione equivalente dal punto di vista semantico ma priva di subquery. In alcuni casi in cui è necessario verificare l'esistenza di dati specifici, tuttavia, l'utilizzo di un join consente di ottenere prestazioni migliori. Se non si utilizza un join, è necessario assicurarsi che i duplicati vengano eliminati elaborando la query nidificata per ogni risultato della query esterna. In questi casi, l'utilizzo del join consente di ottenere risultati migliori. Nell'esempio seguente vengono illustrate un'istruzione SELECT con una subquery e un'istruzione SELECT con un join che restituiscono lo stesso set di risultati:
/* SELECT statement built using a subquery. */
SELECT Name
FROM AdventureWorks.Production.Product
WHERE ListPrice =
(SELECT ListPrice
FROM AdventureWorks.Production.Product
WHERE Name = 'Chainring Bolts' )
/* SELECT statement built using a join that returns
the same result set. */
SELECT Prd1. Name
FROM AdventureWorks.Production.Product AS Prd1
JOIN AdventureWorks.Production.Product AS Prd2
ON (Prd1.ListPrice = Prd2.ListPrice)
WHERE Prd2. Name = 'Chainring Bolts'
Una subquery nidificata nell'istruzione SELECT esterna include i componenti seguenti:
Una normale query SELECT che include i componenti normalmente specificati in un elenco di selezione.
Una normale clausola FROM che include uno o più nomi di tabelle o viste.
Una clausola WHERE facoltativa.
Una clausola GROUP BY facoltativa.
Una clausola HAVING facoltativa.
La query SELECT di una subquery è sempre racchiusa tra parentesi. Non può includere una clausola COMPUTE o FOR BROWSE. È consentita solo una clausola ORDER BY se è specificata anche una clausola TOP.
Una subquery può essere nidificata nella clausola WHERE o HAVING di un'istruzione SELECT, INSERT, UPDATE o DELETE esterna oppure in un'altra subquery. Sono consentiti fino a 32 livelli di nidificazione. Il limite massimo tuttavia varia in base alla memoria disponibile e alla complessità delle altre espressioni della query, ovvero alcune query specifiche potrebbero non supportare 32 livelli di nidificazione. Una subquery può essere specificata in qualsiasi posizione in cui è consentito inserire un'espressione, a condizione che venga restituito un solo valore.
Se una tabella viene specificata in una subquery e non nella query esterna, le colonne di tale tabella non vengono inserite nell'output, ovvero nell'elenco di selezione della query esterna.
Le istruzioni che includono una subquery vengono in genere formulate in uno dei formati seguenti:
WHERE expression [NOT] IN (subquery)
WHERE expression comparison_operator [ANY | ALL] (subquery)
WHERE [NOT] EXISTS (subquery)
In alcune istruzioni Transact-SQL la subquery può essere valutata come se si trattasse di una query indipendente. Concettualmente i risultati della subquery vengono sostituiti nella query esterna, anche se ciò non corrisponde all'effettiva modalità di elaborazione delle istruzioni Transact-SQL con subquery in MicrosoftSQL Server.
Sono disponibili tre tipi di subquery di base, ovvero:
Subquery applicate agli elenchi introdotte da IN oppure introdotte da un operatore di confronto modificato da ANY o ALL.
Subquery introdotte da un operatore di confronto non modificato le quali devono restituire un solo valore.
Subquery che corrispondono a test di esistenza introdotte da EXISTS.