每次更改列值更改时运行的总计

时间:2015-10-23 08:48:23

标签: sql-server tsql ssrs-2008-r2

早上好。

我正在尝试解决一个与下面的帖子非常相似的问题,但是有一个额外的参数让我失望。

SQL Server Query, running total in view, reset when column A changes

在回答这个问题时,提供了以下代码。

原始代码

DECLARE @T TABLE (Category VARCHAR(5), Value INT)
INSERT INTO @T VALUES 
    ('Cat A', 10),
    ('Cat A', 20),
    ('Cat A', 30),
    ('Cat B', 15),
    ('Cat B', 15),
    ('Cat C', 10),
    ('Cat C', 10)

;WITH T AS
(   SELECT  Category, Value, ROW_NUMBER() OVER(PARTITION BY Category ORDER BY Value) [RowNumber]
    FROM    @T
)
SELECT  T1.Category,
        T1.Value,
        RunningTotal
FROM    T T1
        OUTER APPLY
        (   SELECT  SUM(Value) [RunningTotal]
            FROM    T T2
            WHERE   T2.Category = T1.Category
            AND     T2.RowNumber <= T1.RowNumber
        ) RunningTotal

如果类别按顺序排列,此解决方案可正常工作;但是,如果例如订单变为A,A,A,B,B,C,C,A,A,B,那么所有的As将被分组在顶部,然后是B等,并且订单将不会被维护。这可以在下面看到:

扩展示例

DECLARE @T TABLE (Category VARCHAR(5), Value INT)
INSERT INTO @T VALUES 
    ('Cat A', 10),
    ('Cat A', 20),
    ('Cat A', 30),
    ('Cat B', 15),
    ('Cat B', 15),
    ('Cat C', 10),
    ('Cat C', 10),
    ('Cat A', 100),
    ('Cat A', 05),
    ('Cat B', 15)

;WITH T AS
(   SELECT  Category, Value, ROW_NUMBER() OVER(PARTITION BY Category ORDER BY Value) [RowNumber]
    FROM    @T
)
SELECT  T1.Category,
        T1.Value,
        RunningTotal
FROM    T T1
        OUTER APPLY
        (   SELECT  SUM(Value) [RunningTotal]
            FROM    T T2
            WHERE   T2.Category = T1.Category
            AND     T2.RowNumber <= T1.RowNumber
        ) RunningTotal

示例代码输出

╔══════════╦════════╦═══════════════╗
║ Category ║ Amount ║ Running Total ║
╠══════════╬════════╬═══════════════╣
║ Cat A    ║      5 ║             5 ║
║ Cat A    ║     10 ║            15 ║
║ Cat A    ║     20 ║            35 ║
║ Cat A    ║     30 ║            65 ║
║ Cat A    ║    100 ║           165 ║
║ Cat B    ║     15 ║            15 ║
║ Cat B    ║     15 ║            30 ║
║ Cat B    ║     15 ║            45 ║
║ Cat C    ║     10 ║            10 ║
║ Cat C    ║     10 ║            20 ║
╚══════════╩════════╩═══════════════╝

所需输出

我已经添加了一个列来说明我的例子。如下所示,该表按日期排序,因此类别保持该顺序;但是,每次类别更改时,“运行总计”都会重置。

╔══════════╦════════╦═══════════════╦════════════╗
║ Category ║ Amount ║ Running Total ║    Date    ║
╠══════════╬════════╬═══════════════╬════════════╣
║ Cat A    ║     10 ║            10 ║ 23/10/2015 ║
║ Cat A    ║     20 ║            30 ║ 17/10/2015 ║
║ Cat A    ║     30 ║            60 ║ 15/10/2015 ║
║ Cat B    ║     15 ║            15 ║ 02/10/2015 ║
║ Cat B    ║     15 ║            30 ║ 24/09/2015 ║
║ Cat C    ║     10 ║            10 ║ 17/09/2015 ║
║ Cat C    ║     10 ║            20 ║ 14/09/2015 ║
║ Cat A    ║    100 ║           100 ║ 12/09/2015 ║
║ Cat A    ║      5 ║           105 ║ 08/09/2015 ║
║ Cat B    ║     15 ║            15 ║ 03/09/2015 ║
╚══════════╩════════╩═══════════════╩════════════╝

日期相同时的示例

请注意,前两个条目的日期相同。

╔══════════╦═══════╦════════════╦══════════════╗
║ Category ║ Value ║    Date    ║ RunningTotal ║
╠══════════╬═══════╬════════════╬══════════════╣
║ Cat A    ║    10 ║ 30/05/2015 ║           30 ║
║ Cat A    ║    20 ║ 30/05/2015 ║           30 ║
║ Cat A    ║    30 ║ 28/05/2015 ║           60 ║
║ Cat B    ║    15 ║ 27/05/2015 ║           15 ║
║ Cat B    ║    15 ║ 26/05/2015 ║           30 ║
║ Cat C    ║    10 ║ 25/05/2015 ║           10 ║
║ Cat C    ║    10 ║ 24/05/2015 ║           20 ║
║ Cat A    ║   100 ║ 23/05/2015 ║          100 ║
║ Cat A    ║     5 ║ 22/05/2015 ║          105 ║
║ Cat B    ║    15 ║ 21/05/2015 ║           15 ║
╚══════════╩═══════╩════════════╩══════════════╝

类别数量可以更改,最多可以有100个不同的值。

此查询将在SSRS报告中使用,因此,如果有人可以帮助我使用SSRS示例,那将是很好的,如果没有,那么只是SQL也将是惊人的。

非常感谢,

忍。

1 个答案:

答案 0 :(得分:1)

这是一个例子。首先,您要获得岛屿,然后计算运行总数:

DECLARE @T TABLE (Category VARCHAR(5), Value INT, Date DATE)
INSERT INTO @T VALUES 
    ('Cat A', 10, '20150530'),
    ('Cat A', 20, '20150529'),
    ('Cat A', 30, '20150528'),
    ('Cat B', 15, '20150527'),
    ('Cat B', 15, '20150526'),
    ('Cat C', 10, '20150525'),
    ('Cat C', 10, '20150524'),
    ('Cat A', 100, '20150523'),
    ('Cat A', 05, '20150522'),
    ('Cat B', 15, '20150521')

;WITH cte AS(SELECT *, ROW_NUMBER() OVER(Order By date DESC)
              - ROW_NUMBER() OVER(Partition By Category Order By date DESC) rn FROM @t)
SELECT * FROM cte c1
CROSS APPLY(SELECT SUM(c2.Value) AS RunningTotal FROM cte c2 
            WHERE c2.rn = c1.rn AND c2.Category = c1.Category AND c2.Date >= c1.Date) ca
ORDER BY c1.Date desc

输出:

Category    Value   Date        rn  RunningTotal
Cat A       10      2015-05-30  0   10
Cat A       20      2015-05-29  0   30
Cat A       30      2015-05-28  0   60
Cat B       15      2015-05-27  3   15
Cat B       15      2015-05-26  3   30
Cat C       10      2015-05-25  5   10
Cat C       10      2015-05-24  5   20
Cat A       100     2015-05-23  4   100
Cat A       5       2015-05-22  4   105
Cat B       15      2015-05-21  7   15

编辑:

只需在上方添加另一个cte即可获得明确的排序:

;WITH cte1 AS(SELECT *, ROW_NUMBER() OVER(Order By date DESC) rn1 FROM @T),
      cte2 AS(SELECT *, ROW_NUMBER() OVER(Order By rn1)
              - ROW_NUMBER() OVER(Partition By Category Order By rn1) rn2 FROM cte1)
SELECT * FROM cte2 c1
CROSS APPLY(SELECT SUM(c2.Value) AS RunningTotal FROM cte2 c2 
            WHERE c2.rn2 = c1.rn2 AND c2.Category = c1.Category AND c2.rn1 <= c1.rn1) ca
ORDER BY c1.Date desc