Обновить:
В этих статьях моего блога более подробно описаны различия между методами:
Есть три способа выполнить такой запрос:
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
)
Когда table1.common_id
не допускает значения NULL, все эти запросы семантически одинаковы.
Когда он допускает значение NULL, NOT IN
это другое, поскольку IN
(и, следовательно, NOT IN
) возвращается, NULL
когда значение не соответствует чему-либо в списке, содержащем NULL
.
Это может сбивать с толку, но может стать более очевидным, если мы вспомним альтернативный синтаксис для этого:
common_id = ANY
(
SELECT common_id
FROM table1 t1
)
Результатом этого условия является логический продукт всех сравнений в списке. Конечно, одно NULL
значение дает NULL
результат, который также отображает весь результат NULL
.
Мы никогда не можем однозначно сказать, что common_id
не равно чему-либо из этого списка, поскольку есть хотя бы одно из значений NULL
.
Допустим, у нас есть эти данные:
common
--
1
3
table1
--
NULL
1
2
LEFT JOIN / IS NULL
и NOT EXISTS
вернется 3
, ничего неNOT IN
вернет (так как всегда будет оцениваться как или ).FALSE
NULL
В MySQL
случае столбца, не допускающего значения NULL, LEFT JOIN / IS NULL
и NOT IN
они немного (на несколько процентов) более эффективны, чем NOT EXISTS
. Если столбец допускает значение NULL, NOT EXISTS
это наиболее эффективно (опять же, не очень).
В Oracle
все три запроса дают одинаковые планы (an ANTI JOIN
).
In SQL Server
, NOT IN
/ NOT EXISTS
более эффективны, так как LEFT JOIN / IS NULL
не могут быть оптимизированы ANTI JOIN
его оптимизатором.
В PostgreSQL
, LEFT JOIN / IS NULL
и NOT EXISTS
являются более эффективными , чем NOT IN
, синус они оптимизированы для Anti Join
, в то время как NOT IN
использование hashed subplan
(или даже простой , subplan
если подзапрос является слишком большим , чтобы хэш)