Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Umwandlung von NOT IN in NOT EXISTS

Es ist ziemlich einfach, wenn Sie den Bogen raus haben:

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

Diese Zeile vergleicht im Wesentlichen S.S_Id mit allen e.S_Id Werte, die aus der Unterabfrage stammen.

Ändern Sie das jetzt in NOT EXISTS und setzen Sie eine Gleichheitsprüfung S.S_Id = e.S_Id , innerhalb der Unterabfrage:

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

Eine geringfügige mögliche Änderung besteht darin, zu erkennen, dass (SELECT e.S_Id ... benötigt nicht wirklich die e.S_Id . Unterabfragen mit EXISTS und NOT EXISTS Überprüfen Sie einfach, ob Zeilen zurückgegeben werden oder nicht und die Spaltenwerte keine Rolle spielen. Sie können SELECT * eingeben oder dort eine Konstante (SELECT 1 ist üblich) oder SELECT NULL oder sogar SELECT 1/0 (Ja, das geht!):

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

Eine weitere wichtige Überlegung ist, dass, wenn Sie die Konvertierung auf diese Weise durchführen, der (scheinbar äquivalente) NOT EXISTS und NOT IN Die Schreibweisen einer Abfrage sind nur dann wirklich gleichwertig, wenn beide S_Id Spalten sind nicht nullable. Wenn die e.S_Id Spalte ist nullable, der NOT IN kann dazu führen, dass die gesamte Abfrage überhaupt keine Zeilen zurückgibt (weil x NOT IN (a, b, c, ...) entspricht x<>a AND x<>b AND ... und diese Bedingung kann nicht wahr sein, wenn einer der a,b,c... ist NULL .)

Aus ähnlichen Gründen erhalten Sie unterschiedliche Ergebnisse, wenn die s.S_Id ist nullable (das ist in diesem Fall nicht sehr wahrscheinlich, da es wahrscheinlich der Primärschlüssel ist, aber in anderen Fällen ist es wichtig.)

Daher ist es fast immer besser, NOT EXISTS zu verwenden , da es sich anders verhält, selbst wenn eine der Spalten nullfähig ist (die S.S_Id = e.S_Id check verwirft Zeilen mit null früher) und normalerweise ist dieses Verhalten das gewünschte. Die Frage enthält viele Details: NICHT IN vs. NICHT VORHANDEN , in der Antwort von @Martin Smith. Dort finden Sie auch Möglichkeiten, den NOT IN umzuwandeln zu NOT EXISTS und das nullbezogene (unangenehme) Verhalten beibehalten.