2017-07-27 60 views
0

表1:甲骨文有效地接合與子查詢表FROM

| account_no | **other columns**... 
+------------+----------------------- 
| 1   | 
| 2   | 
| 3   | 
| 4   | 

表2:在查詢內部

| account_no | TX_No | Balance | History | 
+------------+-------+---------+------------+ 
| 1   | 123 | 123 | 12.01.2011 | 
| 1   | 234 | 2312 | 01.03.2011 | 
| 3   | 232 | 212 | 19.02.2011 | 
| 4   | 117 | 234 | 24.01.2011 | 

我有多個連接查詢,其中一個表(表2)是有問題的因爲它是一個計算許多其他事物的視圖,所以對該表的每個查詢都是昂貴的。從表2中,對於每一個account_no表1中,我需要整行以最大TX_NO,這是我要做的事:

SELECT * FROM TABLE1 A LEFT JOIN 
      (SELECT 
        X.ACCOUNT_NO, 
        HISTORY, 
        X.BALANCE 
       FROM TABLE2 X INNER JOIN 
       (SELECT 
         ACCOUNT_NO, 
         MAX(TX_NO) AS TX_NO 
       FROM TABLE2 
       GROUP BY ACCOUNT_NO) Y ON X.ACCOUNT_NO = Y.ACCOUNT_NO) B 
      ON B.ACCOUNT_NO = A.ACCOUNT_NO 

正如我先了解它會使內連接所有的行表2和之後,左加入需要account_no表1這是我想避免。

我的問題:有沒有辦法找到max(TX_NO)只爲那些在表1而不是經歷所有的帳戶?我認爲這將有助於提高查詢的速度。

回答

2

我認爲你是在正確的軌道上,但我認爲你不需要,也不會像我自己那樣按照你所做的方式嵌套子查詢。相反,如果你想從表1中的每個記錄,並從表2匹配的最高記錄,你可以嘗試以下方法:

SELECT * FROM TABLE1 t1 
LEFT JOIN 
(
    SELECT t.*, 
     ROW_NUMBER() OVER (PARTITION BY account_no ORDER BY TX_No DESC) rn 
    FROM TABLE2 t 
) t2 
    ON t1.account_no = t2.account_no AND 
     t2.rn = 1 

如果你想繼續你原來的做法,這是我會怎麼做它:

SELECT * 
FROM TABLE1 t1 
LEFT JOIN TABLE2 t2 
    ON t1.account_no = t2.account_no 
INNER JOIN 
(
    SELECT account_no, MAX(TX_No) AS max_tx_no 
    FROM TABLE2 
    GROUP BY account_no 
) t3 
    ON t2.account_no = t3.account_no AND 
     t2.TX_No  = t3.max_tx_no 

使用窗函數來查找TABLE2每個帳戶的最大記錄相反的,我們使用第二個加入一個子查詢代替。我希望窗口函數的方法比雙連接方法執行得更好,一旦你習慣了,它甚至可以更容易閱讀。

+0

ughh,是它看起來像一個好主意,應該考慮窗口函數,我會嘗試 – Hatik

+0

是的,它減少了一半的時間,我覺得很棒。唯一的辦法是通過執行窗口函數,就像在你的查詢中,我得到'ORA-30483:窗口函數在這裏是不允許的'錯誤。這就是爲什麼我首先使用'ROW_NUMBER().. as rn'作爲子查詢從另一個選擇中進行選擇,然後使用標準'where where rn = 1' – Hatik

+0

@Hatik是的,你是對的,我更新了我的答案。我沒有太多的示例數據,也很難在SQLFiddle和Rextester上測試Oracle。 –

1

如果table1的是comparatiely更便宜,那麼你可以考慮做一個左外連接第一這將顯着降低的結​​果集,並從該選擇最新的事務ID記錄單獨

select <required columns> from 
(
select f.<required_columns),row_number() over (partition by account_no order by tx_id desc) as rn 
from 
(
    a.*,b.tx_id,b.balance,b.History 
    from table1 a left outer join table2 b 
on a.account_no=b.account_no 
)f 
)g where g.rn=1 
+0

是的,似乎比我在問題中所做的更好的想法 – Hatik