Poddotaz je účinný způsob, jak najít data, která chcete použít pro jiný dotaz. Často se používají v příkazech SELECT a UPDATE, aby byly tyto dotazy efektivnější a snadněji se udržovaly.
Existuje několik různých způsobů použití poddotazů v příkazech UPDATE. Pojďme se na každou z nich podívat.
SET a dílčí dotaz
První metodou, na kterou se podíváme, je použití poddotazu v klauzuli SET příkazu UPDATE.
Řekněme, že jsme měli tabulku produktů, která vypadala takto:
[id tabulky=29 /]
Uchovává několik informací o různých produktech, které společnost prodává.
Předpokládejme, že se společnost rozhodla zvýšit cenu produktu „Couch“ (ID produktu 1). Místo toho, aby stanovili konkrétní cenu, chtějí ji zvýšit o 20 % oproti nejdražšímu produktu, který mají.
K tomu můžeme použít poddotaz v klauzuli SET. Mohli bychom použít samostatné příkazy, ale snáze se to udržuje pomocí jednoho příkazu.
Naše prohlášení by vypadalo takto:
UPDATE product SET price = ( SELECT MAX(price) * 1.2 FROM product ) WHERE product_id = 1;
Můžete vidět, že klauzule SET obsahuje poddotaz, který najde MAX hodnotu sloupce ceny v tabulce produktů a vynásobí ji 1,2, čímž přidá 20 %. Konečně, klauzule WHERE je mimo poddotaz, aby aktualizovala pouze product_id 1, protože se vztahuje spíše na UPDATE než na poddotaz.
Výsledkem bude následující změna:
[id tabulky=30 /]
SET a korelovaný poddotaz
Dalším způsobem, jak použít poddotaz v příkazu UPDATE, je použít korelovaný poddotaz.
Funguje to podobně jako v předchozím příkladu. Korelovaný poddotaz je však poddotaz, který odkazuje na vnější příkaz a může být součástí příkazu UPDATE.
Na základě dat z předchozího příkladu (tabulky produktů) chce firma deaktivovat všechny produkty, které nebyly objednány. Data pro to jsou uložena v tabulce order_line.
Pokud jsme to napsali jako korelovaný poddotaz, bude dotaz vypadat takto:
UPDATE product p SET active = ( SELECT CASE WHEN COUNT(*) > 0 THEN 'Y' ELSE 'N' END FROM order_line o WHERE o.product_id = p.product_id );
Poddotaz provede funkci COUNT pomocí příkazu CASE k určení, zda je vrácená hodnota Y nebo N v závislosti na hodnotě COUNT. Vypočítává se pro každé product_id a odpovídá vnějšímu dotazu.
Výsledkem bude aktivní sloupec pro některé produkty nastavený na Y a pro jiné na N:
[id tabulky=31 /]
WHERE větší než dílčí dotaz
Je možné použít i poddotaz v klauzuli WHERE. Stejně jako v předchozích příkladech to lze provést k odstranění samostatného kroku nalezení hodnoty, která má být aktualizována, a spuštění dotazu k její aktualizaci.
Můžeme pokračovat v práci s naším příkladem z předchozích kroků. Předpokládejme, že společnost chce aktivovat produkty, které mají nadprůměrnou cenu. K tomu můžeme přidat poddotaz do klauzule WHERE.
Nejprve deaktivujte všechny produkty.
UPDATE product SET active = ’N’;
Poté aktualizujte tabulku pomocí našeho dílčího dotazu.
UPDATE product SET active = 'Y' WHERE price > ( SELECT AVG(price) FROM product );
Tím nastavíte aktivní hodnotu na Y pro všechny záznamy, které mají nadprůměrnou cenu.
Tabulka nyní vypadá takto:
[id tabulky=32 /]
Zobrazuje 2 záznamy s aktivní hodnotou Y, protože jsou nadprůměrné.
Tento druh dotazu lze také spustit s jinými operátory, které umožňují jedinou hodnotu, jako je
KDE V Dílčím dotazu
Také můžeme použít poddotaz s operátorem IN v klauzuli WHERE.
Je to podobné jako v předchozím příkladu, který používal operátor větší než pro jednu hodnotu. Operátor IN lze použít na více hodnot.
Řekněme, že společnost chtěla aktualizovat cenu některých produktů, které byly jedinou položkou v kategorii. Ceny by bylo třeba snížit na polovinu.
Náš dotaz může vypadat takto:
UPDATE product SET price = price / 2 WHERE category_id IN ( SELECT category_id FROM product GROUP BY category_id HAVING COUNT(*) = 1 );
Poddotaz najde všechny hodnoty category_id, kde COUNT je 1. Nemusíme mít COUNT v části SELECT poddotazu, ale pokud ano, dotaz zobrazí chybu.
Příkaz UPDATE aktualizuje cenu, pokud kategorie splňuje kritéria dílčího dotazu.
Naše výsledky pak budou vypadat takto:
[id tabulky=33 /]
Data vypadají velmi podobně. U produktu s ID kategorie 1 se však cena aktualizovala na polovinu původní ceny, protože se jedná o jediný produkt ve své kategorii.
AKTUALIZOVAT poddotaz
Nakonec můžete použít poddotaz v příkazu UPDATE pro aktualizaci tabulky.
V předchozích příkladech jsme právě použili tabulku produktů. Místo tabulky produktů však můžete použít poddotaz, který vrátí sadu výsledků, kterou lze aktualizovat.
Sada výsledků musí být aktualizovatelná, podobně jako v případě, kdy vytvoříte objekt VIEW a pokusíte se jej aktualizovat. Musí to být jednoduché a mít primární klíč.
S využitím našich předchozích příkladů tedy předpokládejme, že společnost chce změnit kategorii pro všechny produkty, které jsou v kategorii 4, na kategorii 5.
Náš dotaz může vypadat takto:
UPDATE ( SELECT product_id, category_id FROM product) SET category_id = 5 WHERE category_id = 4;
Je to jednoduchý příklad, který demonstruje koncept. Tabulka byla nahrazena příkazem SELECT, který zobrazuje pouze dva sloupce tabulky.
Výsledky tohoto dotazu by byly:
[id tabulky=34 /]
Stejného výsledku lze dosáhnout přesunutím klauzule WHERE do příkazu UPDATE:
UPDATE ( SELECT product_id, category_id FROM product WHERE category_id = 4) SET category_id = 5;
Závěr
Použití poddotazu v příkazu UPDATE může být dobrým způsobem, jak zlepšit udržovatelnost vašich dotazů. Může také snížit počet kroků potřebných k aktualizaci dat komprimací dvou nebo více dotazů do jednoho dotazu.