Доста е просто, когато хванете цаката:
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);
Този ред основно сравнява S.S_Id
с всички e.S_Id
стойности, които идват от подзаявката.
Сега променете това на NOT EXISTS
и поставете проверка за равенство S.S_Id = e.S_Id
, вътре в подзаявката:
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);
Малка възможна промяна е да осъзнаете, че (SELECT e.S_Id ...
всъщност не се нуждае от e.S_Id
. Подзаявки с EXISTS
и NOT EXISTS
просто проверете дали има върнати редове или не и стойностите на колоните нямат значение. Можете да поставите SELECT *
или константа там (SELECT 1
е често срещано) или SELECT NULL
или дори SELECT 1/0
(Да, това ще свърши работа!):
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);
Друго важно съображение е, че когато извършвате преобразуването по този начин, (привидно еквивалентно) NOT EXISTS
и NOT IN
писанията на заявка са наистина еквивалентни само ако и двата S_Id
колоните не могат да се нулират. Ако e.S_Id
колоната е nullable, NOT IN
може да доведе до това, че цялата заявка не връща никакви редове (защото x NOT IN (a, b, c, ...)
е еквивалентен на x<>a AND x<>b AND ...
и това условие не може да бъде вярно, когато едно от a,b,c...
е NULL
.)
По подобни причини ще имате различни резултати, ако s.S_Id
е nullable (това не е много вероятно в този случай, тъй като вероятно е първичният ключ, но в други случаи има значение.)
Така че почти винаги е по-добре да използвате NOT EXISTS
, тъй като се държи различно дори ако някоя от колоните е nullable (S.S_Id = e.S_Id
check ще отхвърли редове с null по-рано) и обикновено това поведение е желаното. Във въпроса има много подробности: НЕ В срещу НЕ СЪЩЕСТВУВА
, в отговора на @Martin Smith. Там също ще намерите начини за конвертиране на NOT IN
на NOT EXISTS
и запазете нулевото (неприятно) поведение.