В чем разница между использованием LEFT OUTER JOIN
, а не подзапросом, который начинается с WHERE NOT EXISTS (...)
?
Являются ли понятия SQL 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 всегда будет таким же быстрым или быстрым, так что это хорошая привычка.