2017-11-26 17 views
0

1つの支払いに複数の割り当てがあるため、最初の一致(rownum = 1の場合)のみを考慮する必要があるため、サブクエリを結合に追加する必要があります。ジョインのサブクエリは、where句の外部クエリのテーブルを使用する必要がありますか?

しかし、外部クエリからpmtを割り振り結合のサブクエリに追加するのが最適かどうかはわかりません。

パフォーマンスヒットなどの場合は、これを別の方法で行う必要がありますか?

 SELECT 
      pmt.payment_uid, 
      alt.allotment_uid, 

     FROM 
      payment pmt 

/* HERE: is the reference to pmt.pay_key and pmt.client_id 
    incorrect in the below subquery? */ 

      INNER JOIN allotment alc ON alt.allotment_uid = (
       SELECT 
        allotment_uid 
       FROM 
        allotment 
       WHERE 
         pay_key = pmt.pay_key 
        AND 
         pay_code = 'xyz' 
        AND 
         deleted = 'N' 
        AND 
         client_id = pmt.client_id 
        AND 
         ROWNUM = 1 
      ) 

     WHERE 

      AND 
       pmt.deleted = 'N' 
      AND 
       pmt.date_paid >= TO_DATE('2017-07-01') 
      AND 
       pmt.date_paid < TO_DATE('2017-10-01') + 1; 
+0

それが正しいかどうかは、実行時にどうなるかによって異なります。 –

+0

私は大きなデータを処理しており、クエリは非常に遅いです。私はこれがパフォーマンスの低下に寄与しているのではないかと疑問に思っています。可能であれば避けなければならないものならば... – NoobSter

+0

そのサブクエリの相関関係は、おそらく遅い原因となり、rownumに依存して "あなたがデータにいくつかの意図的な命令を課す場合を除きます。たとえば、割当テーブルに日付またはタイムスタンプの列がありますか? 「作成日」? (もしそうなら、その列の名前は何ですか?) –

答えて

0

EXPLAIN PLAN出力を表示せずに、問合せのパフォーマンスの問題を特定することは困難です。クエリは、メインクエリのすべてのレコードの割り当てに対して追加のSELECTを実行するように見えます。

ここでは、相関サブクエリを使用しないバージョンです。明らかに私はそれをテストすることができませんでした。これは単純な結合を行い、割り当ての1つを除くすべてのレコードをフィルタリングします。お役に立てれば。

WITH v_payment 
AS 
(
    SELECT 
      pmt.payment_uid, 
      alt.allotment_uid, 
      ROW_NUMBER() OVER(PARTITION BY allotment_id) r_num 
     FROM 
      payment pmt JOIN allotment alt 
          ON (pmt.pay_key = alt.pay_key AND 
           pmt.client_id = alt.client_id) 
     WHERE pmt.deleted = 'N' AND 
      pmt.date_paid >= TO_DATE('2017-07-01') AND 
      pmt.date_paid < TO_DATE('2017-10-01') + 1 AND 
      alt.pay_code = 'xyz' AND 
      alt.deleted = 'N' 
) 
SELECT payment_uid, 
     allotment_uid 
    FROM v_payment 
WHERE r_num = 1; 

これがどのように機能するかを知りましょう。

+0

over節は 'order by'を必要としますが、使用する列は絶対に明白ではありません。 –

+0

私は割り当てIDで注文しました。なぜこれがrownum = 1を使うよりも速いのか説明できますか? – NoobSter

+0

関連するサブクエリは、サブクエリが結果セットの各レコードに対して1回だけではなく実行される結果になります。その結果、パフォーマンスが大幅に低下する可能性があります。最近のOracleは、それらのようなクエリのほとんどを書き直すのに賢明だと言っています。あなたの元のクエリがExplain planを見ずにこれに苦しんでいたかどうかを言うのは難しいです。私は両方のバージョンの説明計画を実行し、結果を比較することをお勧めします。 – Ramesh

0

あなたはそのようにクエリをフレーズできます。私はそうする可能性が高いでしょう:

SELECT . . . 
FROM payment p INNER JOIN 
    (SELECT a.*, 
      ROW_NUMBER() OVER (PARTITION BY pay_key, client_id 
           ORDER BY allotment_uid 
           ) as seqnum 
     FROM allotment a 
     WHERE pay_code = 'xyz' AND deleted = 'N' 
    ) a 
    ON a.pay_key = p.pay_key AND a.client_id = p.client_id AND 
     seqnum = 1 
WHERE p.deleted = 'N' AND 
     p.date_paid >= DATE '2017-07-01' AND 
     p.date_paid < (DATE '2017-10-01') + 1; 
+0

サブクエリでrownum = 1を使用するよりもはるかに速く動作する理由を説明できますか? – NoobSter

関連する問題