Являются ли понятия SQL LEFT OUTER JOIN и WHERE NOT EXISTS в основном одинаковыми?

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

Ответ 1

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

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 */

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

Ответ 2

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

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

EXISTS использует:

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

Ответ 3

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

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

Ответ 4

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

Ответ 5

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

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