sql >> Databáze >  >> RDS >> Sqlserver

SQL select where not in subdotaz nevrací žádné výsledky

Aktualizace:

Tyto články na mém blogu popisují rozdíly mezi metodami podrobněji:

  • 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

Existují tři způsoby, jak provést takový dotaz:

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

Když table1.common_id nemá hodnotu null, všechny tyto dotazy jsou sémanticky stejné.

Pokud je povolena hodnota null, NOT IN je jiný, protože IN (a proto NOT IN ) vrátí NULL když hodnota neodpovídá ničemu v seznamu obsahujícím NULL .

To může být matoucí, ale může to být jasnější, když si vzpomeneme na alternativní syntaxi:

common_id = ANY
(
SELECT  common_id
FROM    table1 t1
)

Výsledkem této podmínky je booleovský součin všech srovnání v seznamu. Samozřejmě, jeden NULL hodnota dává NULL výsledek, který vykreslí celý výsledek NULL taky.

Nikdy nemůžeme s jistotou říci, že common_id se nerovná ničemu z tohoto seznamu, protože alespoň jedna z hodnot je NULL .

Předpokládejme, že máme tato data:

common

--
1
3

table1

--
NULL
1
2

LEFT JOIN / IS NULL a NOT EXISTS vrátí 3 , NOT IN nevrátí nic (protože to bude vždy vyhodnoceno buď jako FALSE nebo NULL ).

V MySQL , v případě sloupce bez možnosti null LEFT JOIN / IS NULL a NOT IN jsou o něco málo (o několik procent) efektivnější než NOT EXISTS . Pokud má sloupec hodnotu null, NOT EXISTS je nejúčinnější (opět nic moc).

V Oracle , všechny tři dotazy poskytují stejné plány (ANTI JOIN ).

V SQL Server , NOT IN / NOT EXISTS jsou efektivnější, protože LEFT JOIN / IS NULL nelze optimalizovat na ANTI JOIN jeho optimalizátorem.

V PostgreSQL , LEFT JOIN / IS NULL a NOT EXISTS jsou efektivnější než NOT IN , protože jsou optimalizovány na Anti Join , zatímco NOT IN používá hashed subplan (nebo dokonce obyčejný subplan pokud je poddotaz příliš velký na hašování)



  1. Jak používat nativní heslo s MySQL 5.7

  2. postgres db soubory - který soubor představuje konkrétní tabulku/index?

  3. Připojení odmítnuto (PGError) (postgresql a rails)

  4. Převést „datetime“ na „datetimeoffset“ v SQL Server (příklady T-SQL)