2017-07-27 12 views
0

表1からサブクエリでテーブルを結合するクエリ内のテーブル(表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 | 

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

表2それは他の多くのものを計算するビューなので、そのテーブルに対する各クエリはコストがかかるのです。表2から、私は最大のTX_NOで行全体を必要とし、表1の各account_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

私はあなたが正しい道にいると思いますが、あなたがしたようにサブクエリを入れ子にする必要はないと思います。あなたは表2から表1と一致する最大レコードから各レコードを取得したい場合は代わりに、あなたは次のことを試すことができます。

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

かなりの減少がResultSetだろうし、それから最新のトランザクションIDのレコードを選ぶ最初の参加やって考えることができ素晴らしいアイデアは、ウィンドウの機能について考える必要があります、私は試してみます – Hatik

+0

はい、それは半分に時間を短縮し、私は素晴らしい見つける。唯一のことは、あなたのクエリのようなウィンドウ関数を実行することによって、 'ORA-30483:ウィンドウ関数はここでは許されません.'エラーが出るということです。それで私は最初に 'ROW_NUMBER().. as rn'をサブクエリーとして別の選択肢を選択し、standart' where rn = 1'を使用しました。 – Hatik

+0

@Hatikはい、あなたは正しいです、私は私の答えを更新しました。サンプル・データがあまりなく、SQLFiddleとRextesterの両方でOracleをテストするのも難しいです。 –

1

table1にcomparatiely安価であるならば、あなたは、左の外側がughh、ええ、それはのように見えただけで

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