2017-10-17 1 views
0

私はsubscriptionテーブルと私が参加する必要があるpaymentsテーブルがあります。 私は2つのオプションの間で決定しようとしており、パフォーマンスが重要な考慮事項です。参加条件または以前のCTEに行番号フィルタを設定する必要がありますか?

以下の2つのオプションのどちらが優れていますか?

のみグループ毎iddate(従ってrow_number()分析機能)ごとに1つの行を取得するために私が必要としています私がインパラを使用していて、これらのテーブルは、大きな(行の複数百万)です。

私は私の質問を説明するためにクエリを短縮しています

OPTION 1:

WITH cte 
    AS (
    SELECT * 
     , SUM(amount) OVER (PARTITION BY id, date) 
     AS sameday_total 
     , ROW_NUMBER() OVER (PARTITION BY id, date ORDER BY purchase_number DESC) 
     AS sameday_rownum 
    FROM payments 
), 
payment 
AS (
    SELECT * 
    FROM cte 
    WHERE sameday_rownum = 1 
    ) 
    SELECT s.* 
     , p.sameday_total 
    FROM subscription 
    INNER JOIN payment ON s.id = p.id 

OPTION 2:

WITH payment 
    AS (
    SELECT * 
      , SUM(payment_amount) OVER (PARTITION BY id, date) 
      AS sameday_total 
      , ROW_NUMBER() OVER (PARTITION BY id, date ORDER BY purchase_number DESC) 
      AS sameday_rownum 
    FROM payments 
) 
SELECT s.* 
     , p.sameday_total 
FROM subscription 
INNER JOIN payment ON s.id = p.id 
        AND p.sameday_rownum = 1 
+1

条件を 'on'節に入れてください。 2つのCTEでクエリを混乱させる必要はありません。 –

+0

ありがとうございます。インナー・ジョイントなので、パフォーマンスへの影響はありません。私はこれが最終的なSQLステートメントのSQL述語のwhere節フィルタリングとジョイン条件フィルタリングのパフォーマンスに似ているのだろうかと思ったのですか? – cdabel

+2

クエリプランを見て、オプティマイザが最初または最後にフィルタを適用するかどうかを確認する必要があります。 – Connor

答えて

1

アン "オプション0" も存在します。単にCTEの使用を必要としない従来の「派生テーブル」です。

SELECT s.* 
     , p.sameday_total 
FROM subscription 
INNER JOIN (
      SELECT * 
      , SUM(payment_amount) OVER (PARTITION BY id, date) 
       AS sameday_total 
      , ROW_NUMBER() OVER (PARTITION BY id, date ORDER BY purchase_number DESC) 
       AS sameday_rownum 
      FROM payments 
      ) p ON s.id = p.id 
        AND p.sameday_rownum = 1 

すべてのオプション0,1および2は、(私はインパラよりもSQL Serverのその文の詳細確信していますが)同一または説明非常によく似た計画を生成する可能性があります。

CTEを採用することで、クエリの効率性やパフォーマンスが向上しないため、オプション1と2の間の構文変更は重要ではありません。特定のタスク(たとえば、再帰)にCTEを使用する方が好きなので、私は自分でオプション0を優先します。

あなたがすべきことは、各オプションが何を生産するかを調べるためにはuse explain plansです。

関連する問題