В чем разница между NOT EXISTS и NOT IN против LEFT JOIN, ГДЕ НУЛЬ? - PullRequest
135 голосов
/ 11 февраля 2010

Мне кажется, что вы можете сделать то же самое в запросе 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

Я не уверен, правильно ли я понял весь синтаксис, но это общие приемы, которые я видел. Почему я решил бы использовать один поверх другого? Отличается ли производительность ...? Какой из них самый быстрый / самый эффективный? (Если это зависит от реализации, когда я буду использовать каждый из них?)

Ответы [ 5 ]

127 голосов
/ 11 февраля 2010

В двух словах:

NOT IN немного отличается: он никогда не совпадает, если в списке есть только один NULL.

  • В MySQL, NOT EXISTS немного менее эффективен

  • В SQL Server, LEFT JOIN / IS NULL менее эффективен

  • В PostgreSQL, NOT IN менее эффективен

  • В Oracle все три метода одинаковы.

5 голосов
/ 11 февраля 2010

Если база данных хороша для оптимизации запроса, два первых будут преобразованы во что-то, близкое к третьему.

Для простых ситуаций, подобных тем, о которых вы говорите, различий не должно быть или почти не должнопоскольку они все будут выполнены как объединения.В более сложных запросах база данных может быть не в состоянии объединить запросы not in и not exists.В этом случае запросы станут намного медленнее.С другой стороны, объединение может также работать плохо, если нет индекса, который можно использовать, так что если вы используете объединение, это еще не значит, что вы в безопасности.Вам нужно будет изучить план выполнения запроса, чтобы определить, есть ли проблемы с производительностью.

2 голосов
/ 07 июля 2016

Предполагая, что вы избегаете нулей, все они представляют собой способ anti-join с использованием стандартного 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;
0 голосов
/ 12 марта 2015

С точки зрения производительности всегда избегайте использования обратных ключевых слов, таких как NOT IN, NOT EXISTS, ... Потому что для проверки обратных элементов СУБД необходимо пройти через все доступные и отбросить обратный выбор.

0 голосов
/ 29 апреля 2010

Когда нужно вставить данные в таблицу с многопольным первичным ключом, учтите, что будет намного быстрее (я пытался в Access, но я думаю, в любой базе данных) не проверять, что «не существует записей с« такими »значениями table ", - достаточно просто вставить в таблицу, и лишние записи (по ключу) не будут вставлены дважды.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...