2017-07-27 59 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