Atualização:
Estes artigos no meu blog descrevem as diferenças entre os métodos com mais detalhes:
NOT INvs.NOT EXISTSvs.LEFT JOIN / IS NULL:SQL ServerNOT INvs.NOT EXISTSvs.LEFT JOIN / IS NULL:PostgreSQLNOT INvs.NOT EXISTSvs.LEFT JOIN / IS NULL:OracleNOT INvs.NOT EXISTSvs.LEFT JOIN / IS NULL:MySQL
Existem três maneiras de fazer essa consulta:
-
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 )
Quando
table1.common_id não é anulável, todas essas consultas são semanticamente iguais. Quando é anulável,
NOT IN é diferente, pois IN (e, portanto, NOT IN ) return NULL quando um valor não corresponde a nada em uma lista contendo um NULL . Isso pode ser confuso, mas pode se tornar mais óbvio se lembrarmos a sintaxe alternativa para isso:
common_id = ANY
(
SELECT common_id
FROM table1 t1
)
O resultado desta condição é um produto booleano de todas as comparações dentro da lista. Claro, um único
NULL valor produz o NULL resultado que renderiza todo o resultado NULL também. Nunca podemos dizer com certeza que
common_id não é igual a nada desta lista, pois pelo menos um dos valores é NULL . Suponha que temos estes dados:
common
--
1
3
table1
--
NULL
1
2
LEFT JOIN / IS NULL e NOT EXISTS retornará 3 , NOT IN retornará nada (já que sempre será avaliado como FALSE ou NULL ). Em
MySQL , no caso de coluna não anulável, LEFT JOIN / IS NULL e NOT IN são um pouco (vários por cento) mais eficientes que NOT EXISTS . Se a coluna for anulável, NOT EXISTS é o mais eficiente (novamente, não muito). Em
Oracle , todas as três consultas geram os mesmos planos (um ANTI JOIN ). Em
SQL Server , NOT IN / NOT EXISTS são mais eficientes, pois LEFT JOIN / IS NULL não pode ser otimizado para um ANTI JOIN pelo seu otimizador. Em
PostgreSQL , LEFT JOIN / IS NULL e NOT EXISTS são mais eficientes que NOT IN , pois são otimizados para um Anti Join , enquanto NOT IN usa hashed subplan (ou mesmo um simples subplan se a subconsulta for muito grande para hash)