Použití skalárních nebo vícehodnotových poddotazů
Skalární poddotaz je vnitřní příkaz SELECT v rámci vnějšího dotazu, který se zapíše tak, aby vrátil jednu hodnotu. Skalární poddotazy se můžou používat kdekoli ve vnějším příkazu T-SQL, kde je povolený výraz s jednou hodnotou – například v klauzuli SELECT, klauzuli WHERE, klauzuli HAVING nebo dokonce klauzuli FROM. Dají se také použít v příkazech pro úpravy dat, jako je NAPŘÍKLAD UPDATE nebo DELETE.
Poddotazy s více hodnotami, jak název napovídá, můžou vrátit více než jeden řádek. Přesto ale vrátí jeden sloupec.
Skalární poddotazy
Předpokládejme, že chcete načíst podrobnosti poslední objednávky, která byla zadána, za předpokladu, že se jedná o objednávku s nejvyšší hodnotou SalesOrderID .
Pokud chcete najít nejvyšší hodnotu SalesOrderID , můžete použít následující dotaz:
SELECT MAX(SalesOrderID)
FROM Sales.SalesOrderHeader
Tento dotaz vrátí jednu hodnotu, která označuje nejvyšší hodnotu pro ORDERID v tabulce SalesOrderHeader .
Pokud chcete získat podrobnosti o této objednávce, budete možná muset filtrovat tabulku SalesOrderDetails na základě libovolné hodnoty, kterou vrátí výše uvedený dotaz. Tuto úlohu můžete provést tak, že vnořením dotazu načtete maximální hodnotu SalesOrderID v klauzuli WHERE dotazu, který načte podrobnosti objednávky.
SELECT SalesOrderID, ProductID, OrderQty
FROM Sales.SalesOrderDetail
WHERE SalesOrderID =
(SELECT MAX(SalesOrderID)
FROM Sales.SalesOrderHeader);
Pokud chcete napsat skalární poddotaz, zvažte následující pokyny:
- Pokud chcete dotaz označit jako poddotaz, uzavřete ho do závorek.
- Transact-SQL podporuje více úrovní poddotazů. V tomto modulu budeme uvažovat pouze o dvouúrovňových dotazech (jeden vnitřní dotaz v rámci jednoho vnějšího dotazu), ale podporuje se až 32 úrovní.
- Pokud poddotaz vrátí žádné řádky (prázdná sada), výsledek poddotazu je NULL. Pokud je ve vašem scénáři možné, aby se nevrácely žádné řádky, měli byste zajistit, aby vnější dotaz mohl vedle dalších očekávaných výsledků správně zpracovat hodnotu NULL.
- Vnitřní dotaz by měl obecně vracet jeden sloupec. Výběr více sloupců v poddotazu je téměř vždy chybou. Jedinou výjimkou je, pokud je poddotaz zavedený s klíčovým slovem EXISTS.
Skalární poddotaz lze použít kdekoli v dotazu, kde se očekává hodnota, včetně seznamu SELECT. Mohli bychom například rozšířit dotaz, který načetl podrobnosti o nejnovější objednávce, aby zahrnoval průměrné množství objednaných položek, abychom mohli porovnat množství objednané v nejnovější objednávce s průměrem pro všechny objednávky.
SELECT SalesOrderID, ProductID, OrderQty,
(SELECT AVG(OrderQty)
FROM SalesLT.SalesOrderDetail) AS AvgQty
FROM SalesLT.SalesOrderDetail
WHERE SalesOrderID =
(SELECT MAX(SalesOrderID)
FROM SalesLT.SalesOrderHeader);
Poddotazy s více hodnotami
Vícehodnotový poddotaz je vhodný pro vrácení výsledků pomocí operátoru IN. Následující hypotetický příklad vrátí hodnotu CustomerID, SalesOrderID pro všechny objednávky zadané zákazníky v Kanadě.
SELECT CustomerID, SalesOrderID
FROM Sales.SalesOrderHeader
WHERE CustomerID IN (
SELECT CustomerID
FROM Sales.Customer
WHERE CountryRegion = 'Canada');
Pokud byste v tomto příkladu provedli pouze vnitřní dotaz, vrátí se sloupec hodnot CustomerID s řádkem pro každého zákazníka v Kanadě.
V mnoha případech lze poddotazy s více hodnotami snadno zapsat pomocí spojení. Tady je například dotaz, který pomocí spojení vrátí stejné výsledky jako v předchozím příkladu:
SELECT c.CustomerID, o.SalesOrderID
FROM Sales.Customer AS c
JOIN Sales.SalesOrderHeader AS o
ON c.CustomerID = o.CustomerID
WHERE c.CountryRegion = 'Canada';
Jak se tedy rozhodnete, jestli chcete napsat dotaz zahrnující více tabulek jako JOIN nebo poddotaz? Někdy to závisí jen na tom, s čím jste spokojenější. Většina vnořenýchdotazůch U takových dotazů pak neexistuje žádný skutečný rozdíl v zápisu dotazu jedním způsobem vs.
Jedno omezení, které byste měli mít na paměti, je, že při použití vnořeného dotazu můžou výsledky vrácené klientovi obsahovat pouze sloupce z vnějšího dotazu. Pokud tedy potřebujete vracet sloupce z obou tabulek, měli byste dotaz napsat pomocí funkce JOIN.
A konečně existují situace, kdy vnitřní dotaz musí provádět mnohem složitější operace než jednoduché načítání v našich příkladech. Přepsání složitých poddotazů pomocí funkce JOIN může být obtížné. Mnoho vývojářů SQL hledá nejlepší poddotazy pro složité zpracování, protože umožňuje rozdělit zpracování do menších kroků.