È piuttosto semplice, quando ci prendi la mano:
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);
Quella riga fondamentalmente confronta S.S_Id
con tutti gli e.S_Id
valori che provengono dalla sottoquery.
Ora cambialo in NOT EXISTS
e metti un controllo di uguaglianza S.S_Id = e.S_Id
, all'interno della sottoquery:
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);
Una piccola modifica possibile è rendersi conto che (SELECT e.S_Id ...
non ha davvero bisogno del e.S_Id
. Sottoquery con EXISTS
e NOT EXISTS
controlla solo se ci sono righe restituite o meno e i valori delle colonne non contano. Puoi inserire SELECT *
o una costante lì (SELECT 1
è comune) o SELECT NULL
o anche SELECT 1/0
(Sì, funzionerà!):
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);
Un'altra considerazione importante è che quando si esegue la conversione in questo modo, il (apparentemente equivalente) NOT EXISTS
e NOT IN
gli scritti di una query sono realmente equivalenti solo se entrambi S_Id
le colonne non sono annullabili. Se il e.S_Id
la colonna è nullable, il NOT IN
potrebbe far sì che l'intera query non restituisca alcuna riga (perché x NOT IN (a, b, c, ...)
è equivalente a x<>a AND x<>b AND ...
e quella condizione non può essere vera quando uno dei a,b,c...
è NULL
.)
Per ragioni simili, avrai risultati diversi se s.S_Id
è nullable (questo non è molto probabile in questo caso poiché è probabilmente la chiave primaria ma in altri casi è importante.)
Quindi è quasi sempre meglio usare NOT EXISTS
, poiché si comporta in modo diverso anche se una delle colonne è nullable (il S.S_Id = e.S_Id
check scarterà le righe con null in precedenza) e di solito questo comportamento è quello desiderato. Ci sono molti dettagli nella domanda: NON IN vs NON ESISTE
, nella risposta di @Martin Smith. Troverai anche dei modi per convertire il NOT IN
a NOT EXISTS
e mantieni il comportamento correlato (sgradevole) nullo.