Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

SQL wybierz gdzie nie w podzapytaniu nie zwraca żadnych wyników

Aktualizacja:

Te artykuły na moim blogu bardziej szczegółowo opisują różnice między metodami:

  • NOT IN w porównaniu z NOT EXISTS a LEFT JOIN / IS NULL :SQL Server
  • NOT IN w porównaniu z NOT EXISTS a LEFT JOIN / IS NULL :PostgreSQL
  • NOT IN w porównaniu z NOT EXISTS a LEFT JOIN / IS NULL :Oracle
  • NOT IN w porównaniu z NOT EXISTS a LEFT JOIN / IS NULL :MySQL

Takie zapytanie można wykonać na trzy sposoby:

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

Kiedy table1.common_id nie jest nullable, wszystkie te zapytania są semantycznie takie same.

Gdy jest nullable, NOT IN jest inny, ponieważ IN (i dlatego NOT IN ) zwróć NULL gdy wartość nie pasuje do niczego na liście zawierającej NULL .

Może to być mylące, ale może stać się bardziej oczywiste, jeśli przypomnimy sobie alternatywną składnię:

common_id = ANY
(
SELECT  common_id
FROM    table1 t1
)

Wynik tego warunku jest iloczynem logicznym wszystkich porównań na liście. Oczywiście pojedynczy NULL wartość zwraca NULL wynik, który renderuje cały wynik NULL też.

Nigdy nie możemy jednoznacznie stwierdzić, że common_id nie jest równa niczemu z tej listy, ponieważ przynajmniej jedna z wartości to NULL .

Załóżmy, że mamy te dane:

common

--
1
3

table1

--
NULL
1
2

LEFT JOIN / IS NULL i NOT EXISTS zwróci 3 , NOT IN zwróci nic (ponieważ zawsze będzie oceniane jako FALSE lub NULL ).

W MySQL , w przypadku kolumny nie dopuszczającej wartości null, LEFT JOIN / IS NULL i NOT IN są trochę (kilka procent) bardziej wydajne niż NOT EXISTS . Jeśli kolumna dopuszcza wartość null, NOT EXISTS jest najbardziej wydajny (ponownie, niewiele).

W Oracle , wszystkie trzy zapytania dają te same plany (ANTI JOIN ).

W SQL Server , NOT IN / NOT EXISTS są bardziej wydajne, ponieważ LEFT JOIN / IS NULL nie można zoptymalizować do ANTI JOIN przez jego optymalizator.

W PostgreSQL , LEFT JOIN / IS NULL i NOT EXISTS są bardziej wydajne niż NOT IN , ponieważ są zoptymalizowane pod kątem Anti Join , podczas gdy NOT IN używa hashed subplan (lub nawet zwykły subplan jeśli podzapytanie jest zbyt duże do haszowania)



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. scope_identity a ident_current

  2. Osiągnięcie limitu parametrów 2100 (SQL Server) podczas korzystania z Contains()

  3. Jak zwrócić wszystkie wyłączone ograniczenia kluczy obcych w programie SQL Server (przykład T-SQL)

  4. Wybór procesora dla SQL Server 2014 – część 2

  5. Czy istnieje różnica między SQL Server Express (2012) a LocalDB?