Являются ли концепции SQL LEFT OUTER JOIN и WHERE NOT EXISTS в основном одинаковыми? - PullRequest
12 голосов
/ 19 марта 2012

В чем разница между использованием LEFT OUTER JOIN, а не подзапросом, который начинается с WHERE NOT EXISTS (...)?

Ответы [ 5 ]

35 голосов
/ 19 марта 2012

Нет, это не одно и то же, поскольку они не возвращают один и тот же набор строк в наиболее упрощенном случае.

LEFT OUTER JOIN вернет все строки из левой таблицы, где есть строки в связанной таблице, а где нет. Подзапрос WHERE NOT EXISTS() будет возвращать только те строки, в которых отношение не встречается.

Однако, если вы выполнили LEFT OUTER JOIN и искали IS NULL в столбце внешнего ключа в предложении WHERE, вы можете сделать поведение, эквивалентное WHERE NOT EXISTS.

Например, это:

SELECT 
  t_main.*
FROM 
   t_main
   LEFT OUTER JOIN t_related ON t_main.id = t_related.id
/* IS NULL in the WHERE clause */
WHERE t_related.id IS NULL

Эквивалентно этому:

SELECT
  t_main.*
FROM t_main 
WHERE 
  NOT EXISTS (
    SELECT t_related.id 
    FROM t_related 
    WHERE t_main.id = t_related.id
  )

Но этот не эквивалент:

Возвращает строки из t_main, имеющие и не имеющие связанных строк в t_related.

SELECT 
  t_main.*
FROM
  t_main
  LEFT OUTER JOIN t_related ON t_main.id = t_related.id
/* WHERE clause does not exclude NULL foreign keys */

Примечание Это не говорит о том, как запросы компилируются и выполняются, что также отличается - это касается только сравнения наборов строк, которые они возвращают.

5 голосов
/ 19 марта 2012

Поскольку Майкл уже ответил на ваш вопрос, вот краткий пример, чтобы проиллюстрировать разницу:

Table A
Key     Data
1       somedata1
2       somedata2

Table B
Key     Data
1       data1

Левое внешнее соединение:

SELECT *
FROM A
LEFT OUTER JOIN B
ON A.Key = B.Key

Результат:

Key     Data        Key     Data
1       somedata1   1
2       somedata2   null    null

СУЩЕСТВУЕТ использование:

SELECT *
FROM A WHERE EXISTS ( SELECT B.Key FROM B WHERE A.Key = B.Key )

Не существует в:

SELECT *
FROM A WHERE NOT EXISTS ( SELECT B.Key FROM B WHERE A.Key = B.Key )

Результат:

Key     Data        
2       somedata2
2 голосов
/ 19 марта 2012

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

Однако, если они возвращают эквивалентные строки и вам не нужны какие-либо столбцы в правой таблице, тогда, когда существует, вероятно,быть более производительным выбором (по крайней мере, в SQL-сервере, я не знаю о других БД).

0 голосов
/ 10 мая 2019

Я подозреваю, что ОП хотел знать, какая конструкция лучше, когда они функционально одинаковы (т.е. я хочу видеть только те строки, в которых нет совпадений во вторичной таблице).

Таким образом, WHERE NOT EXISTS всегда будет таким же быстрым или быстрым, так что это хорошая привычка.

0 голосов
/ 20 марта 2012

Я подозреваю, что в конечном итоге ответ таков: оба используются (среди прочих конструкций) для выполнения реляционной операции antijoin в SQL.

...