Имеет ли значение порядок соединения в SQL?
Независимо от производительности, получу ли я тот же результат из запросов A и B ниже? Как насчет C и D?
-- A
select *
from a left join b
on <blahblah>
left join c
on <blahblan>
-- B
select *
from a left join c
on <blahblah>
left join b
on <blahblan>
-- C
select *
from a join b
on <blahblah>
join c
on <blahblan>
-- D
select *
from a join c
on <blahblah>
join b
on <blahblan>
3 ответа
За INNER
присоединяется, нет, порядок не имеет значения. Запросы будут возвращать одинаковые результаты, если вы измените выбор SELECT *
в SELECT a.*, b.*, c.*
,
За (LEFT
, RIGHT
или же FULL
) OUTER
присоединения, да, порядок имеет значение - и (обновленные) вещи намного сложнее.
Во-первых, внешние соединения не являются коммутативными, поэтому a LEFT JOIN b
это не то же самое, что b LEFT JOIN a
Внешние объединения также не являются ассоциативными, поэтому в ваших примерах используются оба свойства (коммутативности и ассоциативности):
a LEFT JOIN b
ON b.ab_id = a.ab_id
LEFT JOIN c
ON c.ac_id = a.ac_id
эквивалентно:
a LEFT JOIN c
ON c.ac_id = a.ac_id
LEFT JOIN b
ON b.ab_id = a.ab_id
но:
a LEFT JOIN b
ON b.ab_id = a.ab_id
LEFT JOIN c
ON c.ac_id = a.ac_id
AND c.bc_id = b.bc_id
не эквивалентно:
a LEFT JOIN c
ON c.ac_id = a.ac_id
LEFT JOIN b
ON b.ab_id = a.ab_id
AND b.bc_id = c.bc_id
Еще один (надеюсь, более простой) пример ассоциативности. Думайте об этом как (a LEFT JOIN b) LEFT JOIN c
:
a LEFT JOIN b
ON b.ab_id = a.ab_id -- AB condition
LEFT JOIN c
ON c.bc_id = b.bc_id -- BC condition
Это эквивалентно a LEFT JOIN (b LEFT JOIN c)
:
a LEFT JOIN
b LEFT JOIN c
ON c.bc_id = b.bc_id -- BC condition
ON b.ab_id = a.ab_id -- AB condition
только потому что у нас "красиво" ON
условия. И то и другое ON b.ab_id = a.ab_id
а также c.bc_id = b.bc_id
проверки на равенство и не включают NULL
сравнения.
Вы даже можете иметь условия с другими операторами или более сложными, такими как: ON a.x <= b.x
или же ON a.x = 7
или же ON a.x LIKE b.x
или же ON (a.x, a.y) = (b.x, b.y)
и два запроса все равно будут эквивалентны.
Однако, если любой из них вовлечен IS NULL
или функция, связанная с нулями, такими как COALESCE()
Например, если условие было b.ab_id IS NULL
, тогда два запроса не будут эквивалентны.
Если вы попытаетесь присоединиться к C на поле из B до присоединения к B, то есть:
SELECT A.x, A.y, A.z FROM A
INNER JOIN C
on B.x = C.x
INNER JOIN b
on A.x = B.x
Ваш запрос не удастся, поэтому в этом случае порядок имеет значение.
Для обычных соединений это не так. TableA join TableB
будет производить тот же план выполнения, что и TableB join TableA
(поэтому ваши примеры C и D будут одинаковыми)
для левого и правого присоединения это делает. TableA left Join TableB
отличается от TableB left Join TableA
, Но это то же самое, что TableB right Join TableA
Оптимизатор Oracle выбирает порядок соединения таблиц для внутреннего соединения. Оптимизатор выбирает порядок объединения таблиц только в простых предложениях FROM. Вы можете проверить документацию оракула на их сайте. А для левого, правого внешнего соединения самый голосующий ответ - правильный. Оптимизатор выбирает оптимальный порядок соединения, а также оптимальный индекс для каждой таблицы. Порядок соединения может влиять на то, какой индекс является лучшим выбором. Оптимизатор может выбрать индекс в качестве пути доступа к таблице, если это внутренняя таблица, но не если это внешняя таблица (и дальнейших уточнений нет).
Оптимизатор выбирает порядок объединения таблиц только в простых предложениях FROM. Большинство объединений с использованием ключевого слова JOIN объединяются в простые объединения, поэтому оптимизатор выбирает их порядок объединения.
Оптимизатор не выбирает порядок соединения для внешних объединений; он использует порядок, указанный в заявлении.
При выборе порядка соединения оптимизатор принимает во внимание: размер каждой таблицы. Индексы, доступные для каждой таблицы. Полезен ли индекс для таблицы в определенном порядке соединения. Количество строк и страниц, которые нужно отсканировать для каждой таблицы в каждой таблице. объединить заказ