Oracle使用FROM中的子查询有效地连接表

时间:2017-07-27 05:41:57

标签: sql oracle join oracle10g

表1:

| 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中,对于表1中的每个account_no,我需要整个行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

据我所知,首先它将为 Table2 中的所有行进行内连接,然后在左连接需要account_no Table1 是我想避免的。

我的问题:是否有办法仅针对 Table1 中的帐户找到max(TX_NO)而不是全部?我认为这有助于提高查询速度。

2 个答案:

答案 0 :(得分: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中每个帐户的最大记录,而是使用第二个连接到子查询。我希望窗口函数方法比这种双连接方法表现更好,一旦你习惯它,它甚至可以更容易阅读。

答案 1 :(得分:1)

如果table1比较便宜,那么你可以考虑首先做一个左外连接,这会大大减少结果集,并从那个选择单独的最新事务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