MS Access - Predikáty ANY, SOME, ALL

23. 12. 2012, Vladimír Klaus, přečteno 2436x

SQL

Tyto predikáty rozšiřují již zmíněný predikát EXISTS.

Řekněme tedy, že potřebujeme zjistit, jací zákazníci učinili objednávku za minimálně 1000 korun. Sestavíme jednoduchý vnitřní dotaz, který nám vrátí částky, a pomocí vnější podmínky provedeme filtrování na výsledek - částku, která musí být větší nebo rovna 1000.

SELECT * FROM Zakaznici
WHERE (1000 <= ANY
(SELECT Castka FROM Objednavky
WHERE Objednavky.IdZakaznika = Zakaznici.ID)
)

SQL obrázek

V tomto případě jsme použili predikát ANY, což je totéž, jako predikát SOME. Stačí, aby alespoň jedna hodnota z vnitřního dotazu vyhovovala podmínce, a výsledek bude zařazen do výsledku.

Co se stane, pokud zaměníme ANY za ALL? Dojde k tomu, že vnitřní dotaz bude vykonán zcela stejně, ale hlavní dotaz ovlivní pouze tehdy, pokud všechny objednávky daného zákazníka budou vyšší nebo rovny 1000.

SELECT * FROM Zakaznici
WHERE (1000 <= ALL
(SELECT Castka FROM Objednavky
WHERE Objednavky.IdZakaznika = Zakaznici.ID)
)

SQL obrázek

Když se podíváte na tento výsledek a porovnáte s objednávkami, budete nemile překvapeni. Pouze Jan Kuklík má všechny svoje objednávky alespoň za 1000 korun. Co tam tedy dělají ti další tři? Jsou to shodou okolnosti ti, kteří nemají vůbec žádnou objednávku, což celý dotaz zmate (viz stále zmiňované úskalí, které přináší NULL).

Jak upravit dotaz, aby nevracel takto pochybný výsledek?

SELECT * FROM Zakaznici
WHERE (1000 <= ALL
(SELECT Castka FROM Objednavky
WHERE Objednavky.IdZakaznika = Zakaznici.ID)
) AND EXISTS
(SELECT Castka FROM Objednavky
WHERE Objednavky.IdZakaznika = Zakaznici.ID)

Museli jsme přidat ještě jednu podmínku pomocí predikátu EXISTS, která zajistí, že daný zákazník vůbec nějakou objednávku učinil. Poté už získáme opravdu zákazníka, jehož všechny objednávky splňují danou podmínku.

SQL obrázek