3

うまくいけば、これは SQL Server の経験が豊富な人にとっては十分に簡単です。

アカウントでアクションが発生するたびに更新される顧客ローン活動データのテーブルがあります。たとえば、制限が引き上げられた場合、新しい制限で新しいレコードが作成されます。以前の制限を差し引いた新しい制限が活動量である活動のリストを作成できるようにしたいと考えています。

現時点では次のものがありますが、以前のレコードにアクセスする方法を見つけるのに苦労しています。

SELECT   
    CUSTOMER
    ,LEDGER
    ,ACCOUNT
    ,H.AMOUNT - COALESCE(X.AMOUNT, 0)
FROM 
    dbo.ACTIVITY H WITH (NOLOCK)
LEFT OUTER JOIN 
    (SELECT  
        CUSTOMER
        ,LEDGER
        ,ACCOUNT
        ,ACTIVITY_DATE
        ,AMOUNT
        ,ROW_NUMBER() OVER (PARTITION BY CUSTOMER, LEDGER, ACCOUNT ORDER BY ACTIVITY_DATE ASC) AS ROW_NUMBER
     FROM 
         dbo.ACTIVITY WITH (NOLOCK)) X ON H.CUSTOMER = X.CUSTOMER
                                          AND H.LEDGER = X.LEDGER
                                          AND H.ACCOUNT = X.ACCOUNT

基本的にx.amountは前の記録の場合のみ引き算したいのですが、何日目か分からない場合の引き方がわかりません。

私は私を助けるだろうと思っRow_Number()たが、私はまだ少し困惑している.

皆様からのご連絡をお待ちしております:)

乾杯

4

1 に答える 1

1

ONCEのみを通過するクエリを次に示します。dbo.Activity

    SELECT H.CUSTOMER
          ,H.LEDGER
          ,H.ACCOUNT
          ,MAX(H.ACTIVITY_DATE) ACTIVITY_DATE
          ,SUM(CASE X.I WHEN 1 THEN AMOUNT ELSE -AMOUNT END) AMOUNT
      FROM (SELECT CUSTOMER
                  ,LEDGER
                  ,ACCOUNT
                  ,ACTIVITY_DATE
                  ,AMOUNT
                  ,ROW_NUMBER() OVER (PARTITION BY CUSTOMER, LEDGER, ACCOUNT ORDER BY ACTIVITY_DATE DESC) AS ROW_NUMBER
             FROM dbo.ACTIVITY WITH (NOLOCK)
           ) H
CROSS JOIN (select 1 union all select 2) X(I)
     WHERE ROW_NUMBER - X.I >= 0
  GROUP BY H.CUSTOMER
          ,H.LEDGER
          ,H.ACCOUNT
          ,ROW_NUMBER - X.I;

そして、これが私がテストに使用したいくつかのデータのDDL/DMLです

CREATE TABLE dbo.ACTIVITY(CUSTOMER int, LEDGER int, ACCOUNT int, ACTIVITY_DATE datetime, AMOUNT int)
INSERT dbo.ACTIVITY select
    1,2,3,GETDATE(),123 union all select
    1,2,3,GETDATE()-1,16 union all select
    1,2,3,GETDATE()-2,12 union all select
    1,2,3,GETDATE()-3,1 union all select
    4,5,6,GETDATE(),1000 union all select
    4,5,6,GETDATE()-6,123 union all select
    7,7,7,GETDATE(),99;

代替案

サブクエリを使用して前の行を取得する、より伝統的なアプローチ:

  SELECT CUSTOMER, LEDGER, ACCOUNT, ACTIVITY_DATE,
         AMOUNT - ISNULL((SELECT TOP(1) I.AMOUNT
                            FROM dbo.ACTIVITY I
                           WHERE I.CUSTOMER = O.CUSTOMER
                             AND I.LEDGER = O.LEDGER
                             AND I.ACCOUNT = O.ACCOUNT
                             AND I.ACTIVITY_DATE < O.ACTIVITY_DATE
                        ORDER BY I.ACTIVITY_DATE DESC), 0) AMOUNT
    FROM dbo.ACTIVITY O
ORDER BY CUSTOMER, LEDGER, ACCOUNT, ACTIVITY_DATE;

または、データを 2 回 ROW_NUMBER() し、それらを結合します

   SELECT A.CUSTOMER, A.LEDGER, A.ACCOUNT, A.ACTIVITY_DATE, 
          A.AMOUNT - ISNULL(B.AMOUNT,0) AMOUNT
     FROM (SELECT *, RN=ROW_NUMBER() OVER (partition by CUSTOMER, LEDGER, ACCOUNT
                                          order by ACTIVITY_DATE ASC)
            FROM dbo.ACTIVITY) A
LEFT JOIN (SELECT *, RN=ROW_NUMBER() OVER (partition by CUSTOMER, LEDGER, ACCOUNT
                                          order by ACTIVITY_DATE ASC)
            FROM dbo.ACTIVITY) B ON A.CUSTOMER = B.CUSTOMER
                              AND A.LEDGER = B.LEDGER
                              AND A.ACCOUNT = B.ACCOUNT
                              AND B.RN = A.RN-1 -- prior record
ORDER BY A.CUSTOMER, A.LEDGER, A.ACCOUNT, A.ACTIVITY_DATE;
于 2012-12-11T00:50:10.943 に答える