多个列上的Oracle SQL外连接--miscoding

lou*_*mat 1 sql oracle join

根据 http://www.orafaq.com/node/855 该表中"不完整加入线"的记录

错误的编码方式是:

select *
from T1, T2, T3, T4
where T1.C1 = T2.C1(+)
and T2.C2 = T3.C2(+)
and T3.C3 = T4.C3;
Run Code Online (Sandbox Code Playgroud)

正确的编码方式是:

select *
from T1, T2, T3, T4
where T1.C1 = T2.C1(+)
and T2.C2 = T3.C2(+)
and T3.C3 = T4.C3(+); 
Run Code Online (Sandbox Code Playgroud)

我无法理解.我可能想要在其他表之间进行等连接T3和T4以及外连接.为什么作者说它不正确?

根据http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:5229892958977,

Tom在他的回答中使用了以下示例,该示例与上面列出的"Incomplete Join Trail"示例类似,

select * 
  from t1,t2,t3
 where t1.x = t2.x and t2.y = t3.y(+);
Run Code Online (Sandbox Code Playgroud)

谁能帮我理解这个?

编辑:

如果我错了,请纠正我.根据Allan的回答,以下代码是正确的:

select *
from T1, T2, T3, T4
where T3.C3 = T4.C3
and T1.C1 = T2.C1(+)
and T2.C2 = T3.C2(+);
Run Code Online (Sandbox Code Playgroud)

如果以上是正确的,它是否等同于以下引用的答案?[即,我们可以在oracle的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(+);
Run Code Online (Sandbox Code Playgroud)

All*_*lan 5

内部联接需要存在匹配的行才能返回行.在第一个查询中,行T1必须存在于表T1和T4中,以便返回结果行.由于T1通过经过T2和T3连接到T4,因此这些外连接呈现无关紧要.您可以非常轻松地检查这一点,因为优化器会知道它们是无关紧要的,并会在解释计划中将它们显示为内连接.

您仍然可以在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(+);
Run Code Online (Sandbox Code Playgroud)

顺便提一下,SQL-99语法最近是首选,这将允许您在没有子查询的情况下执行此操作:

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;
Run Code Online (Sandbox Code Playgroud)

最后,在您使用AskTom的示例中,外连接位于链中的最后一个连接,而不是中间连接.那个案子没问题.


关于修订后的问题,新查询不起作用.该where子句未被排序,因此优化器将以与原始查询完全相同的方式处理该子句.据我所知,除了在from条款中使用某种形式的子条款外,没有办法解决这个问题.