例 如下
表 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 復雜度高了一點。