sql >> Base de Datos >  >> RDS >> Sqlserver

SQL select donde no está en la subconsulta no devuelve resultados

Actualización:

Estos artículos en mi blog describen las diferencias entre los métodos con más detalle:

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

Hay tres formas de hacer una consulta de este tipo:

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

Cuando table1.common_id no admite valores NULL, todas estas consultas son semánticamente iguales.

Cuando es anulable, NOT IN es diferente, ya que IN (y, por lo tanto, NOT IN ) devuelve NULL cuando un valor no coincide con nada en una lista que contiene un NULL .

Esto puede ser confuso, pero puede volverse más obvio si recordamos la sintaxis alternativa para esto:

common_id = ANY
(
SELECT  common_id
FROM    table1 t1
)

El resultado de esta condición es un producto booleano de todas las comparaciones dentro de la lista. Por supuesto, un solo NULL valor produce el NULL resultado que representa el resultado completo NULL también.

Nunca podemos decir definitivamente que common_id no es igual a nada de esta lista, ya que al menos uno de los valores es NULL .

Supongamos que tenemos estos datos:

common

--
1
3

table1

--
NULL
1
2

LEFT JOIN / IS NULL y NOT EXISTS devolverá 3 , NOT IN devolverá nada (ya que siempre se evaluará como FALSE o NULL ).

En MySQL , en el caso de una columna no anulable, LEFT JOIN / IS NULL y NOT IN son un poco (varios por ciento) más eficientes que NOT EXISTS . Si la columna es anulable, NOT EXISTS es el más eficiente (de nuevo, no mucho).

En Oracle , las tres consultas arrojan los mismos planes (un ANTI JOIN ).

En SQL Server , NOT IN / NOT EXISTS son más eficientes, ya que LEFT JOIN / IS NULL no se puede optimizar a un ANTI JOIN por su optimizador.

En PostgreSQL , LEFT JOIN / IS NULL y NOT EXISTS son más eficientes que NOT IN , ya que están optimizados para un Anti Join , mientras que NOT IN usa hashed subplan (o incluso un simple subplan si la subconsulta es demasiado grande para hacer hash)