Det er ret simpelt, når du får styr på det:
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);
Den linje sammenligner grundlæggende S.S_Id
med alle e.S_Id
værdier, der kommer fra underforespørgslen.
Skift det nu til NOT EXISTS
og sæt en lighedskontrol S.S_Id = e.S_Id
, inde i underforespørgslen:
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);
Mindre mulig ændring er at indse, at (SELECT e.S_Id ...
har ikke rigtig brug for e.S_Id
. Underforespørgsler med EXISTS
og NOT EXISTS
bare tjek om der er returnerede rækker eller ej, og kolonneværdierne er ligegyldige. Du kan sætte SELECT *
eller en konstant der (SELECT 1
er almindelig) eller SELECT NULL
eller endda SELECT 1/0
(Ja, det vil virke!):
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);
En anden vigtig overvejelse er, at når du udfører konverteringen på denne måde, (tilsyneladende ækvivalent) NOT EXISTS
og NOT IN
skrivninger af en forespørgsel er kun ækvivalente, hvis begge S_Id
kolonner kan ikke nulstilles. Hvis e.S_Id
kolonnen er nullbar, NOT IN
kan resultere i, at hele forespørgslen ikke returnerer nogen rækker overhovedet (fordi x NOT IN (a, b, c, ...)
svarer til x<>a AND x<>b AND ...
og den betingelse kan ikke være sand, når en af a,b,c...
er NULL
.)
Af lignende årsager vil du få andre resultater, hvis s.S_Id
er nullbar (det er ikke særlig sandsynligt i dette tilfælde, da det sandsynligvis er den primære nøgle, men i andre tilfælde betyder det noget.)
Så det er næsten altid bedre at bruge NOT EXISTS
, da den opfører sig anderledes, selvom en af kolonnerne er nul (S.S_Id = e.S_Id
check vil kassere rækker med null tidligere), og normalt er denne adfærd den ønskede. Der er mange detaljer i spørgsmålet: IKKE IN vs IKKE FINDER
, i svaret af @Martin Smith. Du vil også finde måder at konvertere NOT IN
på til NOT EXISTS
og behold den nul-relaterede (ubehagelige) adfærd.