例 如下
表 A
(1--->n) 表B (B 可能为空)
(n---->n)表C
(n---->n)表D
现在有如下问题 在查询的时候我们允许b为空的A数据
Select * from A,B where A.B_AID = B.AID(+)
扩展查询 如果进行B关联C级别的条件过滤
Select * from A,B, C where A.B_AID = B.AID(+) and B.C_AID = C.AID;
这个时候C能够知道B是可以为空的, 这个时候的join效果是, 如果在A关联B B存在的情况下 在使用 C的join 条件进行筛选。 这个时候B为空的A条件还是可以摆查出来的。 只不过数据列B为空而已
再进行扩展筛选 进行C关联D级别的条筛选Select * from A,B,C,D where A.B_AID = B.AID(+) and B.C_AID = C.AID and C.D_AID = D.AID;
这样的D级别的筛选就会破坏B级别的赛选。
这个时候测试效果就是 D 级别的join条件 会破坏 B的left join 效果。
你可能想到改写条件如下
Select * from A,B,C,D where A.B_AID = B.AID(+) and B.C_AID = C.AID and C.D_AID(+) = D.AID; 可惜我测试结果和full join 的效果是一样的,不是oracle高手, 谁知道的留个言火链接 谢谢
=======================================================================
后来找同学帮忙 得知他以前也遇到这情况
改写为如下条件
select * from (Select ....,C.D_AID from A,B,C where A.B_AID = B.AID(+) and B.C_AID = C.AID ) E,D where E.D_AID(+) = D.AID
这样就不会破坏B(+) 效果。
个人理解就是 select 的组织数据效果。具体不清楚 欢迎发言。
=======================================================================
补充:
今天我才知道 left join 和 inner join 栏位是否必填还有关系。
在这个问题上有个地方被欺骗了
就是在 A Left join
B inner JOIN C 的时候 如果 B 的 C 字段是必填的话 那么就相当于 left join。 如果不是必填的话 你必须手动的指示 left join (+) 。
=====================================================================
补充 2012/10/19 发现以上的理解不全面A--B(+) 意思指B 端可为空, 如果 对B -- C 下面的元素进行赛选, 在局部看 B 和 C 的关系是两段都必须存在的, 但是在A -- B(+) 的前提下 C可以为空的, 所以需要使用 B --- C(+) 来进行关联
这样的坏处是可能会加载出 B (存在)-- C (不存在) 这样的错误数据。 当然如果系统中有对这种数据有确实保障的时候可以忽略该问题如果没有确切的保障的话
可能就需要使用 A --- D(+) 其中D 为 select * from B,C where B = C 这样的过滤方式, 但是这样就增加了复杂度, 你需要将可能用到的查询条件和查询结果集在D中 select 一一列出来
在 Select A.*,R1,R2,R3 from A ,(select B.A_Aid,c1,c2,c3,R1,R2,R3 from B,C where B.C_AID= C.Aid) D where A.Aid = B.A_Aid and c1 = ? and c2 = ? ....
Sql 复杂度高了一点。