Влияет ли порядок соединения в 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>
Ответы
Ответ 1
Для 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
, то два запроса не были бы эквивалентны.
Ответ 2
для регулярных объединений, это не так. TableA join TableB
будет выполнять тот же план выполнения, что и TableB join TableA
(поэтому ваши примеры C и D будут одинаковыми)
для объединения слева и справа. TableA left Join TableB
отличается от TableB left Join TableA
, но его значение равно TableB right Join TableA
Ответ 3
Если вы попытаетесь присоединиться к 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
Ваш запрос не будет выполнен, поэтому в этом случае порядок имеет значение.
Ответ 4
Оптимизатор Oracle выбирает порядок соединения таблиц для внутреннего соединения. Оптимизатор выбирает порядок объединения таблиц только в простых предложениях FROM. Вы можете проверить документацию оракула на их сайте. А для левого, правого внешнего соединения самый голосующий ответ - правильный. Оптимизатор выбирает оптимальный порядок соединения, а также оптимальный индекс для каждой таблицы. Порядок соединения может влиять на то, какой индекс является лучшим выбором. Оптимизатор может выбрать индекс в качестве пути доступа к таблице, если это внутренняя таблица, но не если это внешняя таблица (и дальнейших уточнений нет).
Оптимизатор выбирает порядок объединения таблиц только в простых предложениях FROM. Большинство объединений с использованием ключевого слова JOIN объединяются в простые объединения, поэтому оптимизатор выбирает их порядок объединения.
Оптимизатор не выбирает порядок соединения для внешних объединений; он использует порядок, указанный в заявлении.
При выборе порядка соединения оптимизатор принимает во внимание: размер каждой таблицы. Индексы, доступные для каждой таблицы. Полезен ли индекс для таблицы в определенном порядке соединения. Количество строк и страниц, которые нужно отсканировать для каждой таблицы в каждой таблице. объединить заказ