重置值的SQL Server 2008累积和

时间:2015-03-18 04:35:18

标签: sql sql-server-2008

我希望最后一列基于ROW_ID累积,每次重新开始使用' 1'。

最初我的桌子没有ROW_ID,这是使用分区创建的,所以至少我可以隔离我的记录。

它应该一直向下添加Amt + CumulativeSum(第一条记录除外)并在每次Row_ID = 1时重置。

我尝试了几个查询,但它没有给我想要的结果。我试图从几个论坛阅读答案,但无济于事。

有人可以建议最好的方法吗?

为了表示,我使样本表尽可能简单。

    ID  ROW-ID  Amt RunningTotal(Amt)
    1   1       2   2
    2   2       4   6
    3   3       6   12
    4   1       2   2
    5   2       4   6
    6   3       6   12
    7   4       8   20
    8   5       10  30
    9   1       2   2
    10  2       4   6
    11  3       6   12
    12  4       8   20

3 个答案:

答案 0 :(得分:0)

试试这个

SELECT    distinct (T1.ID), 
                T1.ROW_ID, 
                T1.Amt,
                CumulativeSum = 
                CASE 
                WHEN T1.RoW_ID=1  THEN T1.Amt 
                ELSE  T1.Amt+ T2.Amt 
                END                      
FROM            TestSum T1, TestSum T2
WHERE           T1.ID = T2.ID+1

http://sqlfiddle.com/#!6/8b2a2/2

答案 1 :(得分:0)

我们的想法是从R列创建分区。如果1,请先离开R = 1,否则请0。然后是该列的累积总和。当您有分区时,您最终可以计算这些分区中S列的累计总和:

 ---          ---         ---
| 1 |        | 1 |       | 1 |
| 2 |        | 0 |       | 1 |   --prev 1 + 0
| 3 |        | 0 |       | 1 |   --prev 1 + 0         
| 1 |        | 1 |       | 2 |   --prev 1 + 1
| 2 |    =>  | 0 |   =>  | 2 |   --prev 2 + 0
| 3 |        | 0 |       | 2 |   --prev 2 + 0
| 4 |        | 0 |       | 2 |   --prev 2 + 0
| 5 |        | 0 |       | 2 |   --prev 2 + 0
| 1 |        | 1 |       | 3 |   --prev 2 + 1
| 2 |        | 0 |       | 3 |   --prev 3 + 0
 ---          ---         ---

DECLARE @t TABLE ( ID INT, R INT, S INT )

INSERT  INTO @t
VALUES  ( 1, 1, 2 ),
        ( 2, 2, 4 ),
        ( 3, 3, 6 ),
        ( 4, 1, 2 ),
        ( 5, 2, 4 ),
        ( 6, 3, 6 ),
        ( 7, 4, 8 ),
        ( 8, 5, 10 ),
        ( 9, 1, 2 ),
        ( 10, 2, 4 ),
        ( 11, 3, 6 ),
        ( 12, 4, 8 );

MSSQL 2008

WITH    cte1
          AS ( SELECT   ID ,
                        CASE WHEN R = 1 THEN 1
                             ELSE 0
                        END AS R ,
                        S
               FROM     @t
             ),
        cte2
          AS ( SELECT   ID ,
                        ( SELECT    SUM(R)
                          FROM      cte1 ci
                          WHERE     ci.ID <= co.ID
                        ) AS R ,
                        S
               FROM     cte1 co
             )
    SELECT  * ,
            ( SELECT    SUM(S)
              FROM      cte2 ci
              WHERE     ci.R = co.R
                        AND ci.ID <= co.ID
            )
    FROM    cte2 co

MSSQL 2012

WITH    cte
          AS ( SELECT   ID ,
                        SUM(CASE WHEN R = 1 THEN 1
                                 ELSE 0
                            END) OVER ( ORDER BY ID ) AS R ,
                        S
               FROM     @t
             )
    SELECT  * ,
            SUM(s) OVER ( PARTITION BY R ORDER BY ID ) AS T
    FROM    cte

输出:

ID  R   S   T
1   1   2   2
2   1   4   6
3   1   6   12
4   2   2   2
5   2   4   6
6   2   6   12
7   2   8   20
8   2   10  30
9   3   2   2
10  3   4   6
11  3   6   12
12  3   8   20

编辑:

还有一种方法。执行计划然后第一个示例看起来更好:

SELECT  * ,
        CASE WHEN R = 1 THEN S
             ELSE ( SELECT  SUM(S)
                    FROM    @t it
                    WHERE   it.ID <= ot.ID
                            AND it.ID >= ( SELECT   MAX(ID)
                                           FROM     @t iit
                                           WHERE    iit.ID < ot.ID
                                                    AND iit.R = 1
                                         )
                  )
        END
FROM    @t ot

答案 2 :(得分:0)

试试这个

  declare @tb table(ID int, [ROW-ID] int,  Amt money) 
    insert into @tb(ID, [ROW-ID],  Amt) values
        (1,1,2),
        (2,2,4),
        (3,3,6),
        (4,1,2),
        (5,2,4),
        (7,4,8),
        (8,5,10),
        (9,1,2),
        (10,2,4),
        (11,3,6),
        (12,4,8)
select *,sum(amt) over(partition by ([id]-[row-id]) order by id,[row-id]) AS cum from @tb

其他版本

select *,(select sum(amt) from @tb t where
         (t.id-t.[row-id])=(t1.id-t1.[ROW-ID]) and (t.id<=t1.id) ) as cum 
         from @tb t1 order by t1.id,t1.[row-id]