2017-01-27 2 views
0

私はドナーのグループを持っていて、彼らは不規則に寄付をしているとしましょう。寄付者名、寄付金額、寄付日をテーブルに入れることができますが、その情報のすべてにその金額の後のすべての寄付金の価値を加えたレポートを作成したいと考えています。イベント以降のすべてのトランザクションの合計はどのようにして求められますか?

私はこれをループを使って解析できますが、より良い方法はありますか?

私はここで、ドナーがトランザクション番号を割り当て、すべてが正しい順序であることを確認するコードを気にしないで、不正行為をしています。それだけで十分です。

DECLARE @Donors TABLE (
      ID    INT IDENTITY 
     , Name    NVARCHAR(30) 
     , NID    INT 
     , Amount   DECIMAL(7,2) 
     , DonationDate  DATE 
     , AmountAfter  DECIMAL(7,2) 
     ) 

    INSERT INTO @Donors VALUES 
      ('Adam Zephyr',1,100.00,'2017-01-14',NULL) 
     , ('Adam Zephyr',2,200.00,'2017-01-17',NULL) 
     , ('Adam Zephyr',3,150.00,'2017-01-20',NULL) 
     , ('Braden Yu',1,50.00,'2017-01-11',NULL) 
     , ('Braden Yu',2,75.00,'2017-01-19',NULL) 

    DECLARE @Counter1  INT = 0 
      , @Name   NVARCHAR(30) 

    WHILE @Counter1 < (SELECT MAX(ID) FROM @Donors) 
     BEGIN 
      SET @Counter1 += 1 
      SET @Name = (SELECT Name FROM @Donors WHERE ID = @Counter1) 
      UPDATE d1 
       SET AmountAfter = (SELECT ISNULL(SUM(Amount),0) FROM @Donors d2 WHERE ID > @Counter1 AND Name = @Name) 
        FROM @Donors d1 
         WHERE d1.ID = @Counter1 
     END 

    SELECT * FROM @Donors 

これを再帰的に行う方法があるはずですが、私はそれを回避することができません。

答えて

0

これは、私がドナーであり、その人が寄付したすべての金額の合計であると推定されるNameあたりの最新の寄付を示します。おそらく、パーティションにNIDを使用する方が適切でしょう。

;with MostRecentDonations as (
    select *, 
     row_number() over (partition by Name order by DonationDate desc) as rn, 
     sum(Amount) over (partition by Name) as TotalDonations 
    from @Donors 
) 
select * from MostRecentDonations 
where rn = 1; 

何らかのパフォーマンス上の問題がなければ、どこでも合計を保存する必要はありません。

EDIT: 私はあなたの質問について考えてきたし、今私はあなただけ含まれるすべてのトランザクションで実行中の合計をしたいと考えています。これも簡単です:

select *, 
    sum(Amount) over (partition by Name order by DonationDate) as DonationsToDate 
from @Donors 
order by Name, DonationDate; 
関連する問題