Usare sottoquery scalari o multivalore

Completato

Una sottoquery scalare è un'istruzione SELECT interna a una query esterna, scritta per restituire un singolo valore. Le sottoquery scalari possono essere usate ovunque in un'istruzione T-SQL esterna in cui è consentita un'espressione a valore singolo, ad esempio in una clausola edizione Standard LECT, in una clausola WHERE, in una clausola HAVING o anche in una clausola FROM. Possono essere usate anche nelle istruzioni di modifica dei dati, ad esempio UPDATE o DELETE.

Le sottoquery multivalore, come suggerisce il nome, possono restituire più righe. Tuttavia, restituiscono sempre una singola colonna.

Sottoquery scalari

Si supponga di voler recuperare i dettagli dell'ultimo ordine inserito, presupponendo che sia quello con il valore SalesOrderID più alto.

Per trovare il valore SalesOrderID più alto, è possibile usare la query seguente:

SELECT MAX(SalesOrderID)
FROM Sales.SalesOrderHeader

Questa query restituisce un singolo valore che indica il valore più alto per un oggetto OrderID nella tabella SalesOrderHeader.

Per ottenere i dettagli per questo ordine, potrebbe essere necessario filtrare la tabella SalesOrderDetails in base al valore restituito dalla query precedente. È possibile eseguire questa attività nidificando la query per recuperare il valore massimo di SalesOrderID all'interno della clausola WHERE di una query che recupera i dettagli dell'ordine.

SELECT SalesOrderID, ProductID, OrderQty
FROM Sales.SalesOrderDetail
WHERE SalesOrderID = 
   (SELECT MAX(SalesOrderID)
    FROM Sales.SalesOrderHeader);

Per scrivere una sottoquery scalare, prendere in considerazione le linee guida seguenti:

  • Per indicare una query come sottoquery, racchiuderla tra parentesi.
  • In Transact-SQL sono supportati più livelli di sottoquery. In questo modulo verranno considerate solo query a due livelli, una query interna all'interno di una query esterna, ma sono supportati fino a 32 livelli.
  • Se la sottoquery non restituisce righe, ovvero restituisce un set vuoto, il risultato della sottoquery è NULL. Se nello scenario è previsto che possa non essere restituita alcuna riga, è necessario assicurarsi che la query esterna possa gestire correttamente un valore NULL, oltre ad altri risultati previsti.
  • La query interna deve in genere restituire una singola colonna. La selezione di più colonne in una sottoquery è quasi sempre un errore. L'unica eccezione è se la sottoquery viene introdotta con la parola chiave EXISTS.

Una sottoquery scalare può essere usata in qualsiasi punto di una query in cui è previsto un valore, incluso l'elenco SELECT. Ad esempio, è possibile estendere la query che ha recuperato i dettagli per l'ordine più recente in modo da includere la quantità media di articoli ordinati, per poter confrontare la quantità ordinata nell'ordine più recente con la media per tutti gli ordini.

SELECT SalesOrderID, ProductID, OrderQty,
    (SELECT AVG(OrderQty)
     FROM SalesLT.SalesOrderDetail) AS AvgQty
FROM SalesLT.SalesOrderDetail
WHERE SalesOrderID = 
    (SELECT MAX(SalesOrderID)
     FROM SalesLT.SalesOrderHeader);

Sottoquery multivalore

Una sottoquery multivalore è particolarmente adatta per restituire risultati usando l'operatore IN. Nell'esempio ipotetico seguente vengono restituiti i valori di CustomerID e SalesOrderID per tutti gli ordini inoltrati dai clienti in Canada.

SELECT CustomerID, SalesOrderID
FROM Sales.SalesOrderHeader
WHERE CustomerID IN (
    SELECT CustomerID
    FROM Sales.Customer
    WHERE CountryRegion = 'Canada');

In questo esempio, se si eseguisse solo la query interna verrebbe restituita una colonna di valori CustomerID con una riga per ogni cliente in Canada.

In molti casi le sottoquery multivalore possono essere scritte facilmente usando join. Ad esempio, di seguito è illustrata una query che usa un join per restituire gli stessi risultati dell'esempio precedente:

SELECT c.CustomerID, o.SalesOrderID
FROM Sales.Customer AS c
JOIN Sales.SalesOrderHeader AS o
    ON c.CustomerID = o.CustomerID
WHERE c.CountryRegion = 'Canada';

Come si decide quindi se scrivere una query che interessi più tabelle come JOIN o con una sottoquery? In alcuni casi dipende dalla familiarità con un metodo piuttosto che con l'altro. La maggior parte delle query nidificate facilmente convertibili in JOIN verrà effettivamente convertita in JOIN internamente. Per tali query, non esiste quindi alcuna differenza reale nella scrittura in un modo rispetto all'altro.

Una restrizione da tenere presente è che quando si usa una query nidificata, i risultati restituiti al client possono includere solo colonne della query esterna. Pertanto, se è necessario restituire colonne da entrambe le tabelle, è consigliabile scrivere la query usando un JOIN.

Infine, ci sono situazioni in cui la query interna deve eseguire operazioni molto più complesse rispetto ai semplici recupero negli esempi. La riscrittura di sottoquery complesse tramite JOIN può essere difficile. Molti sviluppatori SQL trovano che le sottoquery funzionino meglio per un'elaborazione complessa perché consentono di suddividere l'elaborazione in passaggi più piccoli.