06.08.2014, Vladimír Klaus, navštíveno 3792x

MS Access
SQL

Příkaz vrátí takové záznamy z prvního dotazu, které nejsou nalezeny ve druhém dotazu. Je to tedy vlastně odečítání, proto se v některých databázích tento příkaz nazývá MINUS. Tento příkaz MS Access ale nezná, a často se dá nahradit příkazem OUTER JOIN. Teď si asi říkáte – ale OUTER JOIN MS Access také nepodporuje, takže jak to tedy bude? Ještě jinak. Další variantou je totiž LEFT JOIN a ten už použít můžeme.

Jako základ vezmeme totéž, co je použito v části Příkaz INTERSECT. Mějme tedy dva základní dotazy – první vypíše zákazníky z Prahy a druhý zákazníky, kteří si objednali alespoň za 2000 Kč.

SELECT * FROM Zakaznici WHERE Mesto LIKE "Praha*"

Příkaz EXCEPT 1

SELECT * FROM Objednavky WHERE Castka >= 2000

Příkaz EXCEPT 2

Nyní nás zajímají zákazníci, kteří jsou sice z Prahy, ale objednali si za méně než 2000 Kč, tedy opravdu chci odečíst výsledek druhého dotazu od výsledku prvního dotazu.

Nejprve začneme běžným spojením pomocí INNER JOIN. Vlevo mám zákazníky z Prahy a vpravo pak připojím jejich objednávky, které jsou alespoň za 2000 Kč.

SELECT Zakaznici.ID, Zakaznici.Prijmeni, Zakaznici.Mesto,
  Objednavky.Castka
    FROM Zakaznici
INNER JOIN
  (SELECT * FROM Objednavky WHERE Castka >= 2000) b
  ON Zakaznici.ID = b.IdZakaznika
  WHERE Zakaznici.Mesto LIKE "Praha*"

Příkaz EXCEPT 3

Když se nyní podíváte na první obrázek se všemi zákazníky z Prahy a tento, zjistíte, že se liší ve třech osobách. A o ty nám nyní jde. Dotaz musíme upravit tak, že změníme spojení na LEFT JOIN. To znamená, že vlevo budou i ty záznamy, kterým na pravé straně neodpovídá žádný záznam, díky nesplněné podmínce na částku. Jinak řečeno – takoví zákazníci, kteří sice mají nějaké objednávky, ale všechny jsou za méně než 2000, proto se k zákazníkovi připojí položky z objednávky, ale budou NULL.

SELECT Zakaznici.ID, Zakaznici.Prijmeni, Zakaznici.Mesto,
  Objednavky.Castka, Objednavky.IdZakaznika
    FROM Zakaznici
LEFT JOIN
  (SELECT * FROM Objednavky WHERE Castka >= 2000) b
  ON Zakaznici.ID = b.IdZakaznika
  WHERE Zakaznici.Mesto LIKE "Praha*"

Příkaz EXCEPT 4

A to už jsme jen kousek od toho, abychom právě tyto prázdné položky využili. Do podmínky doplníme požadavek, aby byl IdZakaznika = NULL. Zároveň odstraníme Castku, protože přestává mít smysl ji vypisovat – bude NULL.

SELECT Zakaznici.ID, Zakaznici.Prijmeni, Zakaznici.Mesto
  FROM Zakaznici
LEFT JOIN
  (SELECT * FROM Objednavky WHERE Castka >= 2000) b
  ON Zakaznici.ID = b.IdZakaznika
  WHERE Zakaznici.Mesto LIKE "Praha*" AND b.IdZakaznika IS NULL

Příkaz EXCEPT 5

Možná se vám to zdá poněkud komplikované a napadne vás, že by to mělo jít řešit jednodušeji – pomocí podmínky Castka < 2000. Vyzkoušejte si to, není to možné.