Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

SQL select where not in subquery gibt keine Ergebnisse zurück

Aktualisierung:

Diese Artikel in meinem Blog beschreiben die Unterschiede zwischen den Methoden genauer:

  • NOT IN vs. NOT EXISTS vs. LEFT JOIN / IS NULL :SQL Server
  • NOT IN vs. NOT EXISTS vs. LEFT JOIN / IS NULL :PostgreSQL
  • NOT IN vs. NOT EXISTS vs. LEFT JOIN / IS NULL :Oracle
  • NOT IN vs. NOT EXISTS vs. LEFT JOIN / IS NULL :MySQL

Es gibt drei Möglichkeiten, eine solche Abfrage durchzuführen:

  • LEFT JOIN / IS NULL :

    SELECT  *
    FROM    common
    LEFT JOIN
            table1 t1
    ON      t1.common_id = common.common_id
    WHERE   t1.common_id IS NULL
    
  • NOT EXISTS :

    SELECT  *
    FROM    common
    WHERE   NOT EXISTS
            (
            SELECT  NULL
            FROM    table1 t1
            WHERE   t1.common_id = common.common_id
            )
    
  • NOT IN :

    SELECT  *
    FROM    common
    WHERE   common_id NOT IN
            (
            SELECT  common_id
            FROM    table1 t1
            )
    

Wenn table1.common_id nicht nullable ist, sind alle diese Abfragen semantisch gleich.

Wenn es nullfähig ist, NOT IN ist anders, da IN (und daher NOT IN ) gibt NULL zurück wenn ein Wert mit nichts in einer Liste übereinstimmt, die einen NULL enthält .

Das mag verwirrend sein, wird aber offensichtlicher, wenn wir uns an die alternative Syntax dafür erinnern:

common_id = ANY
(
SELECT  common_id
FROM    table1 t1
)

Das Ergebnis dieser Bedingung ist ein boolsches Produkt aller Vergleiche innerhalb der Liste. Natürlich ein einzelnes NULL value ergibt den NULL Ergebnis, das das gesamte Ergebnis NULL darstellt auch.

Wir können niemals definitiv sagen, dass common_id ist mit nichts aus dieser Liste gleich, da mindestens einer der Werte NULL ist .

Angenommen, wir haben diese Daten:

common

--
1
3

table1

--
NULL
1
2

LEFT JOIN / IS NULL und NOT EXISTS gibt 3 zurück , NOT IN gibt nichts zurück (da es immer entweder zu FALSE ausgewertet wird oder NULL ).

In MySQL , falls es sich um eine nicht nullfähige Spalte handelt, LEFT JOIN / IS NULL und NOT IN sind etwas (mehrere Prozent) effizienter als NOT EXISTS . Wenn die Spalte nullfähig ist, NOT EXISTS ist am effizientesten (wiederum nicht viel).

In Oracle , ergeben alle drei Abfragen dieselben Pläne (ein ANTI JOIN ).

In SQL Server , NOT IN / NOT EXISTS sind effizienter, da LEFT JOIN / IS NULL kann nicht auf einen ANTI JOIN optimiert werden durch seinen Optimierer.

In PostgreSQL , LEFT JOIN / IS NULL und NOT EXISTS sind effizienter als NOT IN , da sie auf einen Anti Join optimiert sind , während NOT IN verwendet hashed subplan (oder sogar ein einfacher subplan wenn die Unterabfrage zu groß zum Hashen ist)