É bastante simples, quando você pega o jeito:
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);
Essa linha basicamente compara
S.S_Id
com todos os e.S_Id
valores que vêm da subconsulta. Agora mude para
NOT EXISTS
e coloque uma verificação de igualdade S.S_Id = e.S_Id
, dentro da subconsulta: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);
A menor mudança possível é perceber que
(SELECT e.S_Id ...
não precisa realmente do e.S_Id
. Subconsultas com EXISTS
e NOT EXISTS
apenas verifique se há linhas retornadas ou não e os valores das colunas não importam. Você pode colocar SELECT *
ou uma constante lá (SELECT 1
é comum) ou SELECT NULL
ou mesmo SELECT 1/0
(Sim, isso vai funcionar!):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);
Outra consideração importante é que, quando você faz a conversão dessa maneira, o (aparentemente equivalente)
NOT EXISTS
e NOT IN
os escritos de uma consulta são realmente equivalentes apenas se ambos S_Id
colunas não são anuláveis. Se o e.S_Id
coluna é anulável, o NOT IN
pode fazer com que a consulta inteira não retorne nenhuma linha (porque x NOT IN (a, b, c, ...)
é equivalente a x<>a AND x<>b AND ...
e essa condição não pode ser verdadeira quando um dos a,b,c...
é NULL
.) Por motivos semelhantes, você terá resultados diferentes se o
s.S_Id
é anulável (isso não é muito provável neste caso, pois provavelmente é a chave primária, mas em outros casos é importante.) Portanto, é quase sempre melhor usar
NOT EXISTS
, pois ele se comporta de maneira diferente, mesmo que qualquer coluna seja anulável (o S.S_Id = e.S_Id
check descartará linhas com null anteriormente) e geralmente esse comportamento é o desejado. Há muitos detalhes na pergunta: NÃO ESTÁ vs NÃO EXISTE
, na resposta de @Martin Smith. Você também encontrará maneiras de converter o NOT IN
para NOT EXISTS
e manter o comportamento nulo relacionado (desagradável).