2017-07-24 59 views
0

我試圖在Oracle中使用LEFT JOIN連接兩個表。我只需要包含「正確」連接表中的第一條記錄。PL-SQL - 一對多關係中的第一條記錄left join

見下面的例子:

表A

code | emp_no 

101 | 11111 
102 | 22222 
103 | 33333 
104 | 44444 
105 | 55555 

表B

code | city  | county 

101 | City1  | Country1 
101 | City2  | Country1 
101 | City3  | Country1 
102 | City4  | Country2 
103 | City5  | Country3 

預期輸出:

code | emp_no | city  | county 

101 | 11111 | City1  | Country1 
102 | 22222 | City4  | Country2 
103 | 33333 | City5  | Country3 
104 | 44444 | NULL  | NULL 
105 | 55555 | NULL  | NULL 

我需要從表B中選擇第一個匹配的記錄並忽略所有其他行。

上面的查詢猜想作品:

SELECT * 
FROM TABLE_A a 
    LEFT JOIN TABLE_B b ON b.CODE = a.CODE 
     AND b.CODE = 
     (
     SELECT CODE 
     FROM TABLE_B 
     WHERE ROWNUM = 1 
    ) 

但我得到的錯誤: ORA-01799:一列可能不是外連接到一個子查詢

我該怎麼辦這個?使用ROW_NUMBER()函數

感謝

+1

你是如何決定哪個是'第一'? –

+0

注意:目前尚不清楚你想通過只檢索'ROWNUM = 1'來實現。無論如何,我已經寫了答案。 –

回答

3

可以使用min() aggrenate功能與the keep (dense_rank first ...) syntax從外連接表得到「第一」的匹配數據:

select a.code, a.emp_no, 
    min(b.city) keep (dense_rank first order by city, county) as city, 
    min(b.county) keep (dense_rank first order by city, county) as county 
from table_a a 
left join table_b b on b.code = a.code 
group by a.code, a.emp_no 
order by a.code, a.emp_no; 

     CODE  EMP_NO CITY COUNTY 
---------- ---------- ----- -------- 
     101  11111 City1 Country1 
     102  22222 City4 Country2 
     103  33333 City5 Country3 
     104  44444    
     105  55555    

你必須定義什麼「第一」的意思,但 - 我已在keep條款中按順序排列city, county,但您可能有另一個列沒有顯示應該規定訂單。

(您可以爲了通過空使之顯得有些武斷,但是這並不是一個好主意,尤其是更高版本上運行相同的查詢可能會給出同樣的數據不同的結果。)

+0

謝謝亞歷克斯,工作! 只是爲了澄清,我使用BIRT(PL-SQL集成)和我的真實情況,它比這更復雜。 1.我的「第一」行是基於最近更改的(LST_UPD_TSTMP) 2.此問題將與當前包含用戶信息的現有報告(如「ID,名稱...」一起加入) 3. TABLE_B基本上包含: STUD_ID(PK,FK); DEL_STUD_ID(獲得用戶權限的用戶)(PK,FK); LST_UPD_TSTMP(NOT NULL) 4.此後,我需要再次加入以提供有關DEL_STUD_ID的信息 我會嘗試在我的報告中使用此查詢並在此處更新可以嗎? –

+0

@IgorIvanov - 然後聽起來像你需要在'keep'子句中使用'order by lst_upd_tstmp desc'。 (或者,如果你認爲它更好地使用'last'而不是'first',所以你不需要'desc':即'max(b.city)保持(由last_upd_tstmp的最後一個順序的dense_rank)'等) –

+0

Alex Poole,謝謝!它按預期工作! –

1

,並得到記錄,其中row_number()= 1

SELECT select a.code, 
     a.emp_no, 
     b.city, 
     b.county 
FROM table_a a 
     left join (SELECT code, 
         city, 
         county, 
         row_number() 
          over (
          PARTITION BY code 
          ORDER BY city, county) rn 
        FROM table_b) b 
       ON b.code = a.code 
       WHERE rn = 1 OR rn IS NULL; 

注:它仍然是從什麼的問題實際上這意味着目前還不清楚。

first record from the "right" joined table

+1

目前只給出'a'中一個代碼的'b.code'值,並且您已經擁有了這個值;它不會給你任何行的城市/縣? –

+0

我的第一條記錄是基於LST_UPD_TSTMP(真實情況)。我不明白我應該在** id **:'PARTITION BY id'中使用什麼。 –

+0

@IgorIvanov - 看起來你會使用'PARTITION BY code'。但目前不會顯示104或105行;你可以將最後一行改爲'WHERE rn IS NULL OR rn = 1'來修正... –

2

在甲骨文12c你可以使用OUTER APPLYFETCH FIRST條款:

SELECT * 
FROM tableA a 
OUTER APPLY (
    SELECT * FROM tableB b 
    WHERE a.code = b.code 
    ORDER BY city, county 
    FETCH FIRST ROW ONLY 
) 

     CODE  EMP_NO  CODE CITY COUNTY 
---------- ---------- ---------- ----- -------- 
     101  11111  101 City1 Country1 
     102  22222  102 City4 Country2 
     103  33333  103 City5 Country3 
     104  44444       
     105  55555 
+0

謝謝,這很簡單!但它是11g。我們可以在11g上使用類似的東西嗎? –

相關問題