能否請您幫助我?如何從舊的Oracle連接型別轉換為ANSI連接,為什么?
SELECT *
FROM a, b, c
WHERE
b.id ( ) = a.id1
AND b.xxx = c.yyy
AND c.id ( ) = a.id2
--應該是這個1?
select * from
A
left outer join B on B.ID = A.ID1
left outer join C on C. ID = A.ID2 AND B.xxx = C.yyyy
--或者這個2?
select * from
A
left outer join C on C.ID= A.ID2
left outer join B on B. ID = A.ID1 AND B.xxx = C.yyy
uj5u.com熱心網友回復:
根據Oracle的檔案:
如果WHERE子句包含一個將表B的某一列與常數進行比較的條件,那么必須對該列應用( )運算子,以便Oracle從表A回傳對該列產生空值的記錄。否則,Oracle只回傳簡單連接的結果。
所以在b和c之間有一個行內。 而由于整體的條件,這將把所有的連接變成INNER JOIN(在b和c中需要有有效的值才能使這個條件生效。
我認為同等的邏輯是:
SELECT *
FROM a JOIN
b
ON b.id = a.id1 JOIN
c
ON c.id = a.id2 AND b.xxx = c.yyy。
也就是說,簡單的等價消除法將外連接變成了內連接。
當然,你可以對此進行測驗。
uj5u.com熱心網友回復:
如果你運行簡單的explain plan并檢查結果,你可能會看到它生成了兩個inner joins:
explain plan set statement_id = 'test' for
SELECT *
FROM a, b, c
WHERE
b.id ( ) = a.id1
AND b.xxx = c.yyy
AND c.id ( ) = a.id2
select * from table(dbms_xplan.display(null, 'test'))| PLAN_TABLE_OUTPUT || | :--------------------------------------------------------------------------- | | 計劃哈希值: 1502482080 | | | | ---------------------------------------------------------------------------- | | id | operation | name | Rows | Bytes | Cost (%CPU)| Time | | | ---------------------------------------------------------------------------- | | | 0 |選擇陳述句 | | 1 | 78 | 6 (0)| 00:00:01 | | | |* 1 | 散列連接 | | 1 | 78 | 6 (0)| 00:00:01 | | | |* 2 | 散列連接| | 1 | 52 | 4 (0)| 00:00:01 | | | | 3 | 表訪問完整| a | 1 | 26 | 2 (0)| 00:00:01 | | | | 4 | 表訪問完整| b | 1 | 26 | 2 (0)| 00:00:01 | | | | 5 | 表訪問完整| c | 1 | 26 | 2 (0)| 00:00:01 | | | ---------------------------------------------------------------------------- | | | | 謂語資訊(由操作ID識別)。 | | --------------------------------------------------- | | | | 1 - access("B". "XXX"="C". "YYY "AND "C". "ID"="A". "ID2") | 2 - access("B". "ID"="A". "ID1") | | | | 備注 | | ----- | | - 使用的動態統計:動態采樣(級別=2) |
explain plan set statement_id = 'test1' for
select *
from a
left join b
on b.id = a.id1
left join c
on c.id = a.id2
and b.xxx = c.yyy
select * from table(dbms_xplan.display(null, 'test1')| PLAN_TABLE_OUTPUT || | :--------------------------------------------------------------------------- | | 計劃哈希值: 2316364204 | | | | ---------------------------------------------------------------------------- | | id | operation | name | Rows | Bytes | Cost (%CPU)| Time | | | ---------------------------------------------------------------------------- | | | 0 |選擇陳述句 | | 1 | 78 | 6 (0)| 00:00:01 | | | |* 1 | 哈希連接外層 | 1 | 78 | 6 (0)| 00:00:01 | | | |* 2 | 哈希連接外部 | 1 | 52 | 4 (0)| 00:00:01 | | | | 3 | 表訪問完整| a | 1 | 26 | 2 (0)| 00:00:01 | | | | 4 | 表訪問完整| b | 1 | 26 | 2 (0)| 00:00:01 | | | | 5 | 表訪問完整| c | 1 | 26 | 2 (0)| 00:00:01 | | | ---------------------------------------------------------------------------- | | | | 謂語資訊(由操作ID識別)。 | | --------------------------------------------------- | | | | 1 - access("C". "ID"( )="A". "ID2" AND "B". "XXX"="C". "YYY"( )) | | 2 - access("B". "ID"( )="A". "ID1") | | | | 注意 | | ----- | | - 使用的動態統計:動態采樣(級別=2) |
db<>fiddle here
uj5u.com熱心網友回復:
你的兩個選擇:
select *
from A
left outer join B on B.ID= A.ID1
left outer join C on C. ID = A.ID2 AND B.xxx = C.yyyy
將被寫成:
SELECT *
FROM a, b, c
WHERE b.id ( ) = a.id1
AND b.xxx = c.yyy ( )
AND c.id ( ) = a.id2
并且:
select *
from A
left outer join C on C.ID= A.ID2
left outer join B on B. ID = A.ID1 AND B.xxx = C.yyy
將被寫成:
SELECT *
FROM a, b, c
WHERE b.id ( ) = a.id1
and b.xxx ( ) = c.yyy
and c.id ( ) = a.id2
你的情況是:
SELECT *
FROM a
INNER JOIN b ON (a.id1 = b.id)。
INNER JOIN c ON (a. id2 = c.id AND b.xxx = c.yyy)
為什么?
SELECT *
FROM a, b, c
WHERE b.id ( ) = a.id1
AND b.xxx = c.yyy
AND c.id ( ) = a.id2
該行:
AND b.xxx = c.yyy
要求有一個b和一個c行;當有一個左鄰右舍的連接時,這不會發生,所以這個連接相當于一個內部連接,查詢可以改寫成:
SELECT *
FROM a, b, c
WHERE b.id = a.id1
AND b.xxx = c.yyyy
AND c.id = a.id2
然后所有的就更清楚了,所有的連接都是行內。
你可能想寫的是:
select *
from A,
(
SELECT b.id AS b_id。
c.id AS c_id。
b.xxx,
c.yyy
FROM b, c
WHERE b.xxx = c.yyyy
) bc
WHERE bc.b_id ( ) = a.id1
AND bc.c_id ( ) = a.id2
這將是:
select *
from A
left outer join (
SELECT b.id as b_id。
c.id AS c_id。
b.xxx,
c.yyy
FROM b
INNER JOIN c ON b.xxx = c.yyyy
) bc
on bc.b_id = a.id1 AND bc.c_id = a.id2
db<>fiddle here
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/333058.html
標籤:
