sql >> Databasteknik >  >> RDS >> Sqlserver

SQL select where not in subquery returnerar inga resultat

Uppdatering:

Dessa artiklar i min blogg beskriver skillnaderna mellan metoderna mer i detalj:

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

Det finns tre sätt att göra en sådan fråga:

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

När table1.common_id är inte nullbar, alla dessa frågor är semantiskt desamma.

När den är nullbar, NOT IN är annorlunda eftersom IN (och därför NOT IN ) returnera NULL när ett värde inte matchar något i en lista som innehåller en NULL .

Detta kan vara förvirrande men kan bli mer uppenbart om vi minns den alternativa syntaxen för detta:

common_id = ANY
(
SELECT  common_id
FROM    table1 t1
)

Resultatet av detta tillstånd är en boolesk produkt av alla jämförelser i listan. Naturligtvis en enda NULL värde ger NULL resultat som återger hela resultatet NULL också.

Vi kan aldrig säga definitivt att common_id är inte lika med någonting från den här listan, eftersom minst ett av värdena är NULL .

Anta att vi har dessa data:

common

--
1
3

table1

--
NULL
1
2

LEFT JOIN / IS NULL och NOT EXISTS returnerar 3 , NOT IN kommer att returnera inget (eftersom det alltid kommer att utvärderas till antingen FALSE eller NULL ).

I MySQL , i fallet på icke-nullbar kolumn, LEFT JOIN / IS NULL och NOT IN är lite (flera procent) mer effektiva än NOT EXISTS . Om kolumnen är nullbar, NOT EXISTS är den mest effektiva (igen, inte mycket).

I Oracle , ger alla tre frågorna samma planer (en ANTI JOIN ).

I SQL Server , NOT IN / NOT EXISTS är mer effektiva eftersom LEFT JOIN / IS NULL kan inte optimeras till en ANTI JOIN av dess optimerare.

I PostgreSQL , LEFT JOIN / IS NULL och NOT EXISTS är mer effektiva än NOT IN , utan att de är optimerade till en Anti Join , medan NOT IN använder hashed subplan (eller till och med en vanlig subplan om underfrågan är för stor för att hasha)



  1. SQL Server Performance — Testning i molnet

  2. Öppnar Android Sqlite Database i Fragment

  3. Hur man hittar antalet dagar mellan två datum i MySQL

  4. Vänster och höger sammanfogar med hjälp av plustecknet (+) i Oracle