Имеет ли значение порядок соединения в SQL? - PullRequest
159 голосов
/ 08 марта 2012

Независимо от производительности, получу ли я тот же результат из запросов 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>  

Ответы [ 4 ]

196 голосов
/ 08 марта 2012

Для INNER присоединений нет, порядок не имеет значения. Запросы будут возвращать одинаковые результаты, если вы измените выбор с SELECT * на SELECT a.*, b.*, c.*.


Для (LEFT, RIGHT или FULL) OUTER объединений, да, порядок имеет значение - и ( updated ) все гораздо сложнее.

Во-первых, внешние соединения не являются коммутативными, поэтому 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, то эти два запроса не будут эквивалентны.

4 голосов
/ 08 марта 2012

для обычных соединений, это не так. TableA join TableB создаст тот же план выполнения, что и TableB join TableA (поэтому ваши примеры C и D будут такими же)

для левого и правого соединений. TableA left Join TableB отличается от TableB left Join TableA, НО он такой же, как TableB right Join TableA

0 голосов
/ 26 апреля 2019

Оптимизатор Oracle выбирает порядок соединения таблиц для внутреннего соединения.Оптимизатор выбирает порядок объединения таблиц только в простых предложениях FROM.Вы можете проверить документацию оракула на их сайте.А для левого, правого внешнего соединения самый голосующий ответ - правильный.Оптимизатор выбирает оптимальный порядок соединения, а также оптимальный индекс для каждой таблицы.Порядок соединения может влиять на то, какой индекс является лучшим выбором.Оптимизатор может выбрать индекс в качестве пути доступа к таблице, если это внутренняя таблица, но не если это внешняя таблица (и дальнейших уточнений нет).

Оптимизатор выбирает порядок соединения:таблицы только в простых предложениях FROM.Большинство объединений с использованием ключевого слова JOIN объединяются в простые объединения, поэтому оптимизатор выбирает их порядок объединения.

Оптимизатор не выбирает порядок соединения для внешних объединений;он использует порядок, указанный в операторе.

При выборе порядка соединения оптимизатор учитывает: размер каждой таблицы. Индексы, доступные для каждой таблицы. Полезен ли индекс для таблицы вопределенный порядок соединения Число строк и страниц, которые будут сканироваться для каждой таблицы в каждом порядке соединения

0 голосов
/ 09 мая 2018

Если вы попытаетесь присоединиться к 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

ваш запрос не будет выполнен, поэтому в этом случае порядок имеет значение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...