运行Sum,在每个新的连续群集上重置为0

时间:2017-01-18 12:02:27

标签: sql sql-server sql-server-2008

我已经尝试过并且未能适应几种运行总和方法(记住我必须使用SQL Server 2008,因此它比2012年有点棘手)。

目标是按日期排序金额。任何时候类别字段在该列表中更改值,总和应该重新开始。

表格结构:

[Date], [Category], [Amount]

示例:

[Date], [Category], [Amount], [RunSumReset]  
-------------------------------------------
1-Jan,  catA,       10,       10
2-Jan,  catA,       5,        15
3-Jan,  catA,       15,       30
15-Jan, catB,       3,        3
1-Feb,  catB,       6,        9
11-Feb, catA,       10,       10
12-Feb, catC,       2,        2
1-Apr,  catA,       5,        5

非常感谢任何光滑的提示或技巧

2 个答案:

答案 0 :(得分:2)

使用版本2008会使事情变得有点棘手,因为SUM的窗口版本ORDER BY子句不可用。

一种方法是:

WITH CTE AS (
   SELECT [Date], Category, Amount,
          ROW_NUMBER() OVER (ORDER BY [Date]) - 
          ROW_NUMBER() OVER (PARTITION BY Category 
                             ORDER BY [Date]) AS grp
   FROM mytable  
)
SELECT [Date], Category, Amount, Amount + COALESCE(t.s, 0) AS RunSumReset
FROM CTE AS c1
OUTER APPLY (
   SELECT SUM(c2.Amount)
   FROM CTE AS c2
   WHERE c2.[Date] < c1.[Date] AND 
         c1.Category = c2.Category AND 
         c1.grp = c2.grp) AS t(s)
 ORDER BY [Date]   

CTE用于计算字段grp,该字段标识具有相同Category的连续记录的岛。 Category更改后,grp值也会发生变化。使用此CTE,我们可以计算SQL Server 2012之前版本中正常运行方式的运行总计,即使用OUTER APPLY

答案 1 :(得分:1)

选择当前行和第一行中具有不同类别的金额总和。在您的情况下,您需要将NULL替换为SQL Server支持的最短日期,例如'17530101'

DECLARE @t TABLE
    (
      category INT ,
      amount INT ,
      ordering INT
    )
INSERT  INTO @t
VALUES  ( 1, 1, 1 ),
        ( 1, 2, 2 ),
        ( 1, 3, 3 ),
        ( 2, 4, 4 ),
        ( 2, 5, 5 ),
        ( 3, 6, 6 ),
        ( 1, 7, 7 ),
        ( 1, 8, 8 ),
        ( 4, 9, 9 ),
        ( 1, 10, 10 )

SELECT  category ,
        amount ,
        ( SELECT    SUM(amount)
          FROM      @t
          WHERE     category = t.category
                    AND ordering <= t.ordering
                    AND ordering > ( SELECT ISNULL(MAX(ordering), 0)
                                     FROM   @t
                                     WHERE  category <> t.category
                                            AND ordering < t.ordering
                                   )
        ) AS sum
FROM    @t t
ORDER BY t.ordering

输出:

category    amount  sum
1           1       1
1           2       3
1           3       6
2           4       4
2           5       9
3           6       6
1           7       7
1           8       15
4           9       9
1           10      10