Какая разница между NOT EXISTS против NOT IN vs. LEFT JOIN, ГДЕ НАЧАТЬ?
Мне кажется, что вы можете сделать то же самое в SQL-запросе, используя либо NOT EXISTS, NOT IN, либо LEFT JOIN WHERE NULL. Например:
SELECT a FROM table1 WHERE a NOT IN (SELECT a FROM table2)
SELECT a FROM table1 WHERE NOT EXISTS (SELECT * FROM table2 WHERE table1.a = table2.a)
SELECT a FROM table1 LEFT JOIN table2 ON table1.a = table2.a WHERE table1.a IS NULL
Я не уверен, правильно ли я получил синтаксис, но это общие методы, которые я видел. Почему я должен использовать один над другим? Отличается ли производительность...? Какой из них самый быстрый/самый эффективный? (Если это зависит от реализации, когда я буду использовать каждый из них?)
Ответы
Ответ 1
В двух словах:
NOT IN
немного отличается: он никогда не совпадает, если в списке есть только один NULL
.
-
В MySQL
, NOT EXISTS
является немного менее эффективным
-
В SQL Server
, LEFT JOIN / IS NULL
менее эффективен
-
В PostgreSQL
, NOT IN
менее эффективен
-
В Oracle
все три метода одинаковы.
Ответ 2
Если база данных хорошо оптимизирует запрос, два первых будут преобразованы в нечто, близкое к третьему.
Для простых ситуаций, подобных тем, которые вы задаете, разница должна быть небольшой или никакой, поскольку все они будут исполняться как объединения. В более сложных запросах база данных не сможет выполнить соединение с запросами not in
и not exists
. В этом случае запросы будут намного медленнее. С другой стороны, соединение может также плохо работать, если нет индекса, который можно использовать, поэтому только потому, что вы используете соединение, это не значит, что вы в безопасности. Вам нужно будет изучить план выполнения запроса, чтобы определить, могут ли быть проблемы с производительностью.
Ответ 3
Предполагая, что вы избегаете нулей, все они являются способами написания антисоединения с использованием стандартного SQL.
Очевидное упущение эквивалентно с помощью EXCEPT
:
SELECT a FROM table1
EXCEPT
SELECT a FROM table2
Примечание в Oracle вам нужно использовать оператор MINUS
(возможно, лучшее имя):
SELECT a FROM table1
MINUS
SELECT a FROM table2
Говоря о проприетарном синтаксисе, могут также быть нестандартные эквиваленты, которые стоит исследовать в зависимости от продукта, который вы используете, например. OUTER APPLY
в SQL Server (что-то вроде):
SELECT t1.a
FROM table1 t1
OUTER APPLY
(
SELECT t2.a
FROM table2 t2
WHERE t2.a = t1.a
) AS dt1
WHERE dt1.a IS NULL;
Ответ 4
Когда вам нужно вставить данные в таблицу с помощью первичного ключа с несколькими полями, подумайте, что это будет намного быстрее (я пытался в Access, но я думаю, что в любой базе данных), чтобы не проверять, что "не существует записей с" такими "значениями в table", - скорее просто вставьте в таблицу, а лишние записи (по ключу) не будут вставлены дважды.
Ответ 5
Перспектива производительности всегда избегает использования обратных ключевых слов, таких как NOT IN, NOT EXISTS,...
Поскольку для проверки обратных элементов СУБД необходимо выполнить все доступные и отбросить обратный выбор.