Actualización:
Estos artículos en mi blog describen las diferencias entre los métodos con más detalle:
NOT IN
frente aNOT EXISTS
frente aLEFT JOIN / IS NULL
:SQL Server
NOT IN
frente aNOT EXISTS
frente aLEFT JOIN / IS NULL
:PostgreSQL
NOT IN
frente aNOT EXISTS
frente aLEFT JOIN / IS NULL
:Oracle
NOT IN
frente aNOT EXISTS
frente aLEFT 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)