运行 分组记录总数

Running Total by Grouped Records

我有一个门票数据库 table 作为

+------------+-------------+------------+
| CategoryID | RequestDate | FixedDate  |
+------------+-------------+------------+
|          1 | 2014-01-01  | NULL       |
|          1 | 2014-01-02  | 2014-01-05 |
|          1 | 2014-01-28  | 2014-01-30 |
|          2 | 2014-02-20  | NULL       |
|          2 | 2014-03-15  | NULL       |
|          2 | 2014-03-15  | 2014-03-20 |
|          1 | 2014-03-15  | 2014-03-17 |
+------------+-------------+------------+

这是所需的输出:

+-------+------+--------+-------+---------------+
| Month | Year | Opened | Fixed | Running_Total |
+-------+------+--------+-------+---------------+
|     1 | 2014 |      3 |     2 |             1 |
|     2 | 2014 |      1 |     0 |             2 |
|     3 | 2014 |      3 |     2 |             3 |
+-------+------+--------+-------+---------------+

基本上,我希望每个月获得 运行 所有未结门票的总数。我正在尝试使用 CTE,但无法这样做。

非常感谢任何帮助。

试试这个:

DECLARE @t TABLE ( Req DATE, Fixed DATE )

INSERT  INTO @t
VALUES  ( '20140101', NULL ),
        ( '20140102', '20140105' ),
        ( '20140128', '20140330' ),
        ( '20140220', NULL ),
        ( '20140301', NULL ),
        ( '20140301', '20140320' ),
        ( '20140301', '20140317' );
WITH    cte
          AS ( SELECT   ROW_NUMBER() OVER ( ORDER BY YEAR(Req), MONTH(Req) ) AS Rn ,
                        MONTH(Req) Month ,
                        YEAR(Req) Year ,
                        COUNT(*) AS Opened ,
                        COUNT(Fixed) AS Fixed,
                        SUM(CASE WHEN MONTH(req) = MONTH(Fixed) THEN 1 ELSE 0 END) AS Closed                      
               FROM     @t
               GROUP BY MONTH(Req) ,
                        YEAR(Req)
             )
    SELECT  Month, Year, Opened, Fixed , Closed ,
            ( SELECT    SUM(Opened) - SUM(Fixed)
              FROM      cte c1
              WHERE     c1.Rn <= cte.Rn
            ) AS Running_Total 
    FROM    cte

输出:

Month   Year    Opened  Fixed   Closed  Running_Total
1       2014    3       2       1       1
2       2014    1       0       0       2
3       2014    3       2       2       3

你可以不使用 CTE,但不幸的是要复制代码:

SELECT  Month ,
        Year ,
        Opened ,
        Fixed ,
        Closed ,
        ( SELECT    SUM(Opened) - SUM(Fixed)
          FROM      ( SELECT    ROW_NUMBER() OVER ( ORDER BY YEAR(Req), MONTH(Req) ) AS Rn ,
                                COUNT(*) AS Opened ,
                                COUNT(Fixed) AS Fixed
                      FROM      @t
                      GROUP BY  MONTH(Req) ,
                                YEAR(Req)
                    ) c1
          WHERE     c1.Rn <= cte.Rn
        ) AS Running_Total
FROM    ( SELECT    ROW_NUMBER() OVER ( ORDER BY YEAR(Req), MONTH(Req) ) AS Rn ,
                    MONTH(Req) Month ,
                    YEAR(Req) Year ,
                    COUNT(*) AS Opened ,
                    COUNT(Fixed) AS Fixed ,
                    SUM(CASE WHEN MONTH(req) = MONTH(Fixed) THEN 1
                             ELSE 0
                        END) AS Closed
          FROM      @t
          GROUP BY  MONTH(Req) ,
                    YEAR(Req)
        ) cte

构建一个按年和月聚合的查询,然后在游标中使用该查询,然后迭代该游标以计算 运行 总数。

declare @Month int;
declare @Year int;
declare @Opened int;
declare @Fixed int;
declare @Running_Total int = 0;

declare @T table
(
  Month int,
  Year int,
  Opened int,
  Fixed int,
  Running_Total int
);

declare C cursor local static forward_only read_only for
  select T.Month,
         T.Year,
         count(*),
         count(T.FixedDate)
  from (
       select datepart(month, T.RequestDate) as Month,
              datepart(year, T.RequestDate) as Year,
              T.FixedDate
       from dbo.YourTable as T 
       ) as T
  group by T.Year, T.Month
  order by T.Year, T.Month;

open C;
fetch next from C into @Month, @Year, @Opened, @Fixed;

while @@fetch_status = 0
begin
  set @Running_Total = @Running_Total + @Opened - @Fixed;

  insert into @T(Month, Year, Opened, Fixed, Running_Total) 
    values(@Month, @Year, @Opened, @Fixed, @Running_Total);

  fetch next from C into @Month, @Year, @Opened, @Fixed;
end;

close C;
deallocate C;

select Month, Year, Opened, Fixed, Running_Total
from @T;