2009-07-07 2 views
6

Я, наверное, должен это знать до сих пор, но что, если есть разница между двумя утверждениями ниже?SQL - Разница между этими соединениями?

вложенной присоединиться:

SELECT 
    t1.* 
FROM 
    table1 t1 
    INNER JOIN table2 t2 
     LEFT JOIN table3 t3 ON t3.table3_ID = t2.table2_ID 
    ON t2.table2_ID = t1.table1_ID 

Более традиционные JOIN:

SELECT 
    t1.* 
FROM 
    table1 t1 
    INNER JOIN table2 t2 ON t2.table2_ID = t1.table1_ID 
    LEFT JOIN table3 t3 ON t3.table3_ID = t2.table2_ID 
+0

Получают ли они тот же результат при их исполнении? –

+0

+1 за то, что заставило меня пойти «Хм ...» – Tomalak

+0

. Лучше понять второй, чем первый, даже если вы положили (parens) вокруг LOJ в первом. С нетерпением ждем хорошего ответа на этот вопрос. –

ответ

5

Ну, это порядок операций ..

SELECT 
    t1.* 
FROM 
    table1 t1 
    INNER JOIN table2 t2 
     LEFT JOIN table3 t3 ON t3.table3_ID = t2.table2_ID 
    ON t2.table2_ID = t1.table1_ID 

можно переписать в виде:

SELECT 
    t1.* 
FROM 
     table1 t1              -- inner join t1 
    INNER JOIN 
     (table2 t2 LEFT JOIN table3 t3 ON t3.table3_ID = t2.table2_ID) -- with this 
    ON t2.table2_ID = t1.table1_ID          -- on this condition 

так в основном, сначала вы LEFT JOIN t2 t3 с, на основе условия соединения: table3_ID = table2_ID, то вы INNER JOIN t1 с t2 на table2_ID = table1_ID.

В вашем втором примере вы сначала INNER JOIN t1 с t2, а затем LEFT JOIN получившееся внутреннее соединение с таблицей t3 в условии table2_ID = table1_ID.

SELECT 
    t1.* 
FROM 
    table1 t1 
    INNER JOIN table2 t2 ON t2.table2_ID = t1.table1_ID 
    LEFT JOIN table3 t3 ON t3.table3_ID = t2.table2_ID   

можно переписать в виде:

SELECT 
    t1.* 
FROM 
     (table1 t1 INNER JOIN table2 t2 ON t2.table2_ID = t1.table1_ID) -- first inner join 
    LEFT JOIN               -- then left join 
     table3 t3 ON t3.table3_ID = t2.table2_ID      -- the result with this 

EDIT

Я извиняюсь. Мое первое замечание было неправильным. Эти два запроса будут давать одни и те же результаты, но может быть разница в производительности, поскольку первый запрос может выполняться медленнее второго запроса в некоторых случаях (когда таблица 1 содержит только подмножество элементов в таблице 2), поскольку LEFT JOIN будет выполняться сначала - и только затем пересекается с таблицей 1. В отличие от второго запроса, который позволяет оптимизатору запросов выполнять свою работу.

+1

Очевидно, что порядок операций отличается, но есть ли какая-либо фактическая разница (производительность, результаты, что-либо)? –

+1

Просьба привести пример данных, в которых запросы будут возвращать разные результаты. Я не смог сгенерировать их. –

+0

Хорошо, спасибо за мысли об этих парнях. Это почти так, как я тогда думал. Результаты будут одинаковыми, но запросы могут выполняться по-разному. Я считаю, что для удобства использования я изменил старый (вложенный) запрос на использование более традиционного синтаксиса. – TehOne

4

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

Если бы вы обратили внимание на типы объединений в примере, вы могли бы получить очень разные результаты.

SELECT t1.* 
FROM table1 t1 
    LEFT JOIN table2 t2 ON t2.table2_ID = t1.table1_ID 
    INNER JOIN table3 t3 ON t3.table3_ID = t2.table2_ID 

-- may not produce the same results as... 

SELECT t1.* 
FROM table1 t1 
    LEFT JOIN table2 t2 
     INNER JOIN table3 t3 ON t3.table3_ID = t2.table2_ID 
    ON t2.table2_ID = t1.table1_ID 

Исходя из того, что порядок объединений имеет значение во многих случаях - продуманы должны идти в том, как вы пишете ваш присоединиться к синтаксису. Если вы обнаружили, что второй пример того, что вы на самом деле пытаетесь достичь, я бы рассмотреть переписывание запроса, так что вы можете уделять больше внимания на порядок ваших объединений ...

SELECT t1.* 
FROM table2 t2 
     INNER JOIN table3 t3 ON t3.table3_ID = t2.table2_ID 
     RIGHT JOIN table1 t1 ON t2.table2_ID = t1.table1_ID 
2

Лучший способ увидеть, что отличается в этих двух запросах, - сравнить План запросов для обоих этих запросов.

Нет никакой разницы в наборах результатов для этих IF всегда есть строки в таблице3 для данной строки в таблице2.

Я пробовал это в своей базе данных, и разница в запросах заключалась в том, что 1. Для первого запроса оптимизатор решил сначала выполнить соединение на таблице2 и в таблице 3. 2.Во втором запросе оптимизатор решил сначала присоединиться к таблице1 и таблице2.

+0

Для меня планы выполнения моих реальных запросов были точно такими же. – TehOne

0

Вы не должны видеть никакой разницы между двумя запросами, если ваш оптимизатор СУБД до нуля. Это, однако, даже для дорогостоящих платформ с большим утюгом, не является предположением, что я был бы уверен в том, чтобы сделать, поэтому я был бы не удивлен, если бы обнаружил, что планы запросов (и, следовательно, время выполнения) различны.

Смежные вопросы