sql >> Database >  >> RDS >> Sqlserver

SQL selecteer waar niet in subquery geeft geen resultaten

Bijwerken:

Deze artikelen in mijn blog beschrijven de verschillen tussen de methoden in meer detail:

  • 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

Er zijn drie manieren om zo'n zoekopdracht uit te voeren:

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

Wanneer table1.common_id is niet nullable, al deze zoekopdrachten zijn semantisch hetzelfde.

Als het nullable is, NOT IN is anders, aangezien IN (en daarom NOT IN ) retourneer NULL wanneer een waarde niet overeenkomt met iets in een lijst met een NULL .

Dit kan verwarrend zijn, maar kan duidelijker worden als we ons de alternatieve syntaxis hiervoor herinneren:

common_id = ANY
(
SELECT  common_id
FROM    table1 t1
)

Het resultaat van deze voorwaarde is een booleaans product van alle vergelijkingen in de lijst. Natuurlijk, een enkele NULL waarde geeft de NULL resultaat dat het hele resultaat NULL weergeeft ook.

We kunnen nooit met zekerheid zeggen dat common_id is niet gelijk aan iets uit deze lijst, aangezien ten minste één van de waarden NULL . is .

Stel dat we deze gegevens hebben:

common

--
1
3

table1

--
NULL
1
2

LEFT JOIN / IS NULL en NOT EXISTS retourneert 3 , NOT IN retourneert niets (aangezien het altijd zal evalueren naar FALSE of NULL ).

In MySQL , in het geval op een niet-nullable kolom, LEFT JOIN / IS NULL en NOT IN zijn een klein beetje (enkele procenten) efficiënter dan NOT EXISTS . Als de kolom nullable is, NOT EXISTS is het meest efficiënt (nogmaals niet veel).

In Oracle , leveren alle drie de zoekopdrachten dezelfde plannen op (een ANTI JOIN ).

In SQL Server , NOT IN / NOT EXISTS zijn efficiënter, aangezien LEFT JOIN / IS NULL kan niet worden geoptimaliseerd tot een ANTI JOIN door zijn optimalisatieprogramma.

In PostgreSQL , LEFT JOIN / IS NULL en NOT EXISTS zijn efficiënter dan NOT IN , omdat ze zijn geoptimaliseerd voor een Anti Join , terwijl NOT IN gebruikt hashed subplan (of zelfs een gewoon subplan als de subquery te groot is om te hashen)



  1. Hoe Trunc() werkt in PostgreSQL

  2. Query schrijven voor meerdere tabellen in php

  3. Aan de slag met MariaDB met Docker, Java Spring en JDBC

  4. Handmatig nieuwe RAC-instantie toevoegen