Je to docela jednoduché, když to pochopíte:
SELECT s.S_Fname, s.S_Lname
FROM STUDENT s
WHERE s.S_Sex = 'F'
AND S.S_Id NOT IN(SELECT e.S_Id -- take this line
FROM ENROLLMENT e
WHERE e.Mark < 70);
Tento řádek v podstatě porovnává S.S_Id se všemi e.S_Id hodnoty, které pocházejí z poddotazu.
Nyní to změňte na NOT EXISTS a zadejte kontrolu rovnosti S.S_Id = e.S_Id , uvnitř poddotazu:
SELECT s.S_Fname, s.S_Lname
FROM STUDENT s
WHERE s.S_Sex = 'F'
AND NOT EXISTS (SELECT e.S_Id
FROM ENROLLMENT e
WHERE (e.Mark < 70) -- if this is complex, you'll need parentheses
AND S.S_Id = e.S_Id);
Menší možná změna je uvědomit si, že (SELECT e.S_Id ... ve skutečnosti nepotřebuje e.S_Id . Dílčí dotazy s EXISTS a NOT EXISTS stačí zkontrolovat, zda jsou vráceny řádky nebo ne, a na hodnotách sloupců nezáleží. Můžete zadat SELECT * nebo tam konstanta (SELECT 1 je běžné) nebo SELECT NULL nebo dokonce SELECT 1/0 (Ano, to bude fungovat!):
SELECT s.S_Fname, s.S_Lname
FROM STUDENT s
WHERE s.S_Sex = 'F'
AND NOT EXISTS (SELECT 1
FROM ENROLLMENT e
WHERE e.Mark < 70
AND S.S_Id = e.S_Id);
Dalším důležitým aspektem je, že když provedete převod tímto způsobem, (zdánlivě ekvivalentní) NOT EXISTS a NOT IN zápisy dotazu jsou skutečně ekvivalentní, pouze pokud jsou oba S_Id sloupce nemají hodnotu null. Pokud e.S_Id sloupec má hodnotu null, NOT IN může způsobit, že celý dotaz nevrátí vůbec žádné řádky (protože x NOT IN (a, b, c, ...) je ekvivalentní x<>a AND x<>b AND ... a tato podmínka nemůže být pravdivá, když jeden z a,b,c... je NULL .)
Z podobných důvodů budete mít jiné výsledky, pokud s.S_Id má nulovou hodnotu (v tomto případě to není příliš pravděpodobné, protože se pravděpodobně jedná o primární klíč, ale v jiných případech na tom záleží.)
Téměř vždy je tedy lepší použít NOT EXISTS , protože se chová odlišně, i když je v každém sloupci povolena hodnota Null (S.S_Id = e.S_Id check zahodí řádky s null dříve) a toto chování je obvykle žádoucí. V otázce je mnoho podrobností: NENÍ IN vs. NEEXISTUJE
, v odpovědi @Martin Smith. Najdete zde také způsoby, jak převést NOT IN na NOT EXISTS a zachovat nulové (nepříjemné) chování.