2013-06-05 57 views
1

我有一個簡單的SQL查詢的奇怪行爲。我從事Oracle 9i。 我只是想確保在我的查詢中沒有愚蠢的錯誤。如果有人能告訴我我做錯了什麼。這裏的查詢:Oracle 9i SQL查詢 - 多次連接同一個表

select p.PARTNUM, 
     p.N_DATAA, dataa1.ID_DATA as ID_DATAA, 
     p.N_DATAF, dataf1.ID_DATA as ID_DATAF, 
     p.N_DATAS, datas1.ID_DATA as ID_DATAS 
from PIECES p 
left join DATA dataa1 on 
       dataa1.N_DATA = p.N_DATAA AND 
       dataa1.REV_DATA = (select max(dataa2.REV_DATA) from DATA dataa2 
            where dataa2.N_DATA = p.N_DATAA) 
left join DATA dataf1 on 
       dataf1.N_DATA = p.N_DATAF AND 
       dataf1.REV_DATA = (select max(dataf2.REV_DATA) from DATA dataf2 
            where dataf2.N_DATA = p.N_DATAF) 
left join DATA datas1 on 
       datas1.N_DATA = p.N_DATAS AND 
       datas1.REV_DATA = (select max(datas2.REV_DATA) from DATA datas2 
            where datas2.N_DATA = p.N_DATAS) 
where p.PARTNUM='MYPARTNUM'; 

這裏是結果:

"PARTNUM"  "N_DATAA" "ID_DATAA" "N_DATAF" "ID_DATAF" "N_DATAS" "ID_DATAS"      
"MYPARTNUM" "A23240" "300"  "F4130"  "398"  "S2330"  ""     

場上ID_DATAS出現我的問題(一個ID_DATAS應該返回,我敢肯定,見下文),它的作用如果它忽略最後的連接並檢索不到數據。如果我刪除了第二個連接,它完美的工作。這似乎是,如果Oracle不支持超過2左加入...(???)

這裏當我切換了最後兩個左連接(在這種情況下出現在ID_DATAF問題)的其他例子:

select p.PARTNUM, 
     p.N_DATAA, dataa1.ID_DATA as ID_DATAA, 
     p.N_DATAF, dataf1.ID_DATA as ID_DATAF, 
     p.N_DATAS, datas1.ID_DATA as ID_DATAS 
from PIECES p 
left join DATA dataa1 on 
       dataa1.N_DATA = p.N_DATAA AND 
       dataa1.REV_DATA = (select max(dataa2.REV_DATA) from DATA dataa2 
            where dataa2.N_DATA = p.N_DATAA) 
left join DATA datas1 on 
       datas1.N_DATA = p.N_DATAS AND 
       datas1.REV_DATA = (select max(datas2.REV_DATA) from DATA datas2 
            where datas2.N_DATA = p.N_DATAS) 
left join DATA dataf1 on 
       dataf1.N_DATA = p.N_DATAF AND 
       dataf1.REV_DATA = (select max(dataf2.REV_DATA) from DATA dataf2 
            where dataf2.N_DATA = p.N_DATAF) 
where p.PARTNUM='MYPARTNUM'; 

這裏是結果:

"PARTNUM"  "N_DATAA" "ID_DATAA" "N_DATAF" "ID_DATAF" "N_DATAS" "ID_DATAS"      
"MYPARTNUM" "A23240" "300"  "F4130"  ""   "S2330"  "400"   

謝謝您的幫助:)

編輯:在查詢中添加完全合格的列名(不解決我的問題)

+1

你應該總是使用完全合格的列名 - 尤其是如果超過這些存在的列一張桌子。在這種情況下,如果您在某個時候升級到當前(=支持的)版本的Oracle,您的查詢將會失敗。 –

+0

謝謝a_horse_with_no_name ^^,你是完全正確的,但是我沒有使用完全限定列名的列確實只存在於一個表中。我已經嘗試了爲每個列提供完全合格的列名稱,但它不能解決我的問題:( – Matth

+0

問題編輯爲在查詢中使用完全限定的列名稱,建議使用a_horse_with_no_name。 – Matth

回答

2

您可能遇到了您的舊版本Oracle的錯誤。 Oracle 9i是第一個支持ANSI連接的版本,並帶有ANSI連接語法的一些缺陷。

您的查詢將不會以跟上時代的(11.2)Oracle數據庫(SQLFiddle)運行,你會遇到:

ORA-01799: a column may not be outer-joined to a subquery 

因此,在您的Oracle版本的bug是,這個查詢不該不會返回任何結果。無論如何,請確保您正在運行最新的補丁集。此外,它可能是一個好主意,計劃升級,此版本已棄用 - 擴展支持已結束3年前!

你必須重寫查詢,比如像這樣的:只要你有一個以上的表

SQL> WITH filtered_data AS (
    2  SELECT n_data, rev_data, id_data 
    3  FROM DATA d 
    4  WHERE rev_data = (SELECT MAX(rev_data) 
    5       FROM DATA d_in 
    6       WHERE d_in.n_data = d.n_data) 
    7 ) 
    8 SELECT p.partnum, 
    9   p.n_dataa, 
10   A.id_data AS id_dataa, 
11   p.n_dataf, 
12   F.id_data AS id_dataf, 
13   p.n_datas, 
14   S.id_data AS id_datas 
15 FROM pieces p 
16 LEFT JOIN filtered_data A ON A.n_data = p.n_dataa 
17 LEFT JOIN filtered_data S ON S.n_data = p.n_datas 
18 LEFT JOIN filtered_data F ON F.n_data = p.n_dataf 
19 WHERE p.PARTNUM = 'MYPARTNUM'; 

PARTNUM  N_DATAA ID_DATAA N_DATAF ID_DATAF N_DATAS ID_DATAS 
------------- -------- --------- -------- --------- -------- --------- 
MYPARTNUM  A23240 300  F4130 398  S2330 400 
+0

OMG!非常感謝您的詳細解答!!! – Matth

+0

工程就像一個魅力!:) – Matth