sql >> Database >  >> RDS >> Oracle

Omzetten van NOT IN naar NOT EXISTS

Het is vrij eenvoudig, als je het onder de knie hebt:

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);

Die regel vergelijkt in feite S.S_Id met alle e.S_Id waarden die uit de subquery komen.

Verander dat nu in NOT EXISTS en plaats een gelijkheidscontrole S.S_Id = e.S_Id , in de subquery:

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);

Een kleine mogelijke verandering is om te beseffen dat (SELECT e.S_Id ... heeft de e.S_Id niet echt nodig . Subquery's met EXISTS en NOT EXISTS controleer gewoon of er rijen zijn geretourneerd of niet en de kolomwaarden doen er niet toe. U kunt SELECT * of een constante daar (SELECT 1 is gebruikelijk) of SELECT NULL of zelfs SELECT 1/0 (Ja, dat zal werken!):

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);

Een andere belangrijke overweging is dat wanneer u de conversie op deze manier uitvoert, de (schijnbaar equivalente) NOT EXISTS en NOT IN geschriften van een query zijn alleen echt equivalent als beide S_Id kolommen zijn niet nullable. Als de e.S_Id kolom is nullable, de NOT IN kan ertoe leiden dat de hele zoekopdracht helemaal geen rijen retourneert (omdat x NOT IN (a, b, c, ...) is gelijk aan x<>a AND x<>b AND ... en die voorwaarde kan niet waar zijn als een van de a,b,c... is NULL .)

Om vergelijkbare redenen krijgt u andere resultaten als de s.S_Id is nullable (dat is in dit geval niet erg waarschijnlijk omdat het waarschijnlijk de primaire sleutel is, maar in andere gevallen is het van belang.)

Het is dus bijna altijd beter om NOT EXISTS . te gebruiken , omdat het zich anders gedraagt, zelfs als een van beide kolommen nullable is (de S.S_Id = e.S_Id check verwijdert eerder rijen met null) en meestal is dit het gewenste gedrag. De vraag bevat veel details: NIET IN vs NIET BESTAAT , in het antwoord van @Martin Smith. Je zult ook manieren vinden om de NOT IN . te converteren naar NOT EXISTS en behoud het null-gerelateerde (onaangename) gedrag.



  1. Hoe tel je het aantal keren dat een bepaald woord voorkomt in een MySQL-blob-tekst?

  2. hoe laadtijd in milliseconden of microseconden in mysql te krijgen

  3. Excel verbinden met PostgreSQL via VBA

  4. Hoe u Limit dynamisch kunt wijzigen in mySQL