sql >> Database teknologi >  >> RDS >> Oracle

Konvertering af NOT IN til NOT EXISTS

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.



  1. Sådan opdaterer du en kolonne baseret på et filter af en anden kolonne

  2. Hvordan json_encode array med franske accenter?

  3. Oracle Protocol Adapter Fejl

  4. er min store mysql-tabel bestemt til at fejle?