Oracle SQL внешнее объединение по нескольким столбцам - PullRequest
1 голос
/ 02 сентября 2011

Согласно http://www.orafaq.com/node/855 Запись в этой таблице для "Incomplete Join Trail"

Неправильный способ кодирования:

select *
from T1, T2, T3, T4
where T1.C1 = T2.C1(+)
and T2.C2 = T3.C2(+)
and T3.C3 = T4.C3;

Правильный способ кодирования:

select *
from T1, T2, T3, T4
where T1.C1 = T2.C1(+)
and T2.C2 = T3.C2(+)
and T3.C3 = T4.C3(+); 

Это я не мог понять.Существует вероятность, что я мог бы сделать равное соединение T3 и T4 и внешнее соединение между другими таблицами.Почему автор говорит, что это неверно?

В соответствии с http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:5229892958977,

Том использует в своем ответе следующий пример, который кажется похожим на приведенный выше пример «Незавершенного соединения»

select * 
  from t1,t2,t3
 where t1.x = t2.x and t2.y = t3.y(+);

Может ли кто-нибудь помочь мне понять это?

Редактировать:

Пожалуйста, исправьте меня, если я ошибаюсь.Согласно ответу Аллана, следующий код будет правильным:

select *
from T1, T2, T3, T4
where T3.C3 = T4.C3
and T1.C1 = T2.C1(+)
and T2.C2 = T3.C2(+);

Если вышеприведенное верно, будет ли это эквивалентно следующему цитируемому ответу? [Т.е., можем ли мы сделать это в sql оракула безподзапрос в цитируемом ответе?]

SELECT *
FROM   t1, t2, (SELECT *
                FROM   t3, t4
                WHERE  t3.c3 = t4.c3) t3_4
WHERE  t1.c1 = t2.c1(+) AND t2.c2 = t3_4.c2(+);

1 Ответ

5 голосов
/ 02 сентября 2011

Внутренние объединения требуют наличия соответствующей строки для возврата строки.В вашем первом запросе строки должны присутствовать в таблицах T1 и T4, чтобы полученная строка была возвращена.Поскольку T1 соединяется с T4, проходя через T2 и T3, эти внешние соединения оказываются несущественными.Вы можете легко проверить это, так как оптимизатор будет знать, что они не имеют значения, и покажет их как внутренние объединения в плане объяснения.

Вы все еще можете иметь внутреннее соединение между T3 и T4, но вам нужночтобы сделать это в подзапросе, чтобы сделать внешнее объединение с функционалом T2:

SELECT *
FROM   t1, t2, (SELECT *
                FROM   t3, t4
                WHERE  t3.c3 = t4.c3) t3_4
WHERE  t1.c1 = t2.c1(+) AND t2.c2 = t3_4.c2(+);

Кстати, синтаксис SQL-99 в наши дни предпочтителен, что позволит вам делать это без вложенного запроса.query:

SELECT *
FROM              t1
       LEFT JOIN  t2
               ON t1.c1 = t2.c1
       LEFT JOIN  (t3
       JOIN       t4
               ON t3.c3 = t4.c3)
               ON t2.c2 = t3.c2;

Наконец, в примере, который вы используете из AskTom, внешнее соединение - это последнее соединение в цепочке, а не середина.С этим делом все в порядке.


Что касается пересмотренного вопроса, новый запрос не будет работать.Предложение where не упорядочено, поэтому оптимизатор будет обрабатывать его точно так же, как и исходный запрос.Насколько я знаю, нет никакого способа решить эту проблему, кроме использования какой-либо формы подпункта в предложении from.

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