SQL 服务器:按日期变化计算总数的类型

SQL Server : count types with totals by date change

我需要在日期 (RS_Date) 的每次更改时计算一个值 (M_Id),并创建一个按 RS_Date 分组的列,该列具有来自该日期的活动总数日期。

所以 table 是:

Ep_Id   Oa_Id   M_Id M_StartDate    RS_Date
--------------------------------------------
    1   2001    5   1/1/2014       1/1/2014
    1   2001    9   1/1/2014       1/1/2014
    1   2001    3   1/1/2014       1/1/2014
    1   2001    11  1/1/2014       1/1/2014
    1   2001    2   1/1/2014       1/1/2014
    1   2067    7   1/1/2014       1/5/2014
    1   2067    1   1/1/2014       1/5/2014
    1   3099    12  1/1/2014       3/2/2014
    1   3099    14  2/14/2014      3/2/2014
    1   3099    4   2/14/2014      3/2/2014

所以我的目标是

RS_Date   Active
-----------------
1/1/2014    5
1/5/2014    7
3/2/2014    10

如果 M_startDate = RS_Date 我需要计算 M_id 然后 每个不等于开始日期的 RS_Date 我需要计算 M_Id 然后将其添加到 M_StartDate 计数然后计算下一个 RS_Date 并将其添加到最后一个活动计数。

我可以通过类似

的方式获得基本计数
(Case when M_StartDate <= RS_Date
        then [m_Id] end) as Test.

但我不知道如何获得我想要的结果。

如有任何帮助,我们将不胜感激。

布莱恩

-为回应评论而添加 我正在使用服务器版本 10

如果您使用的是 SQL 2012 或更新版本,您可以使用 LAG 生成 运行 总数。

https://msdn.microsoft.com/en-us/library/hh231256(v=sql.110).aspx

您需要一个累计总和,在 SQL Server 2012 中使用窗口聚合函数很容易。根据您的描述,这将 return 预期结果

SELECT p_id, RS_Date,
   SUM(COUNT(*)) 
   OVER (PARTITION BY p_id 
         ORDER BY RS_Date 
         ROWS UNBOUNDED PRECEDING)
FROM tab
GROUP BY p_id, RS_Date

如果使用 SQL SERVER 2012+,您可以将 ROWS 与 analytic/window 函数一起使用:

;with cte AS (SELECT RS_Date
                    ,COUNT(DISTINCT M_ID) AS CT
              FROM Table1
              GROUP BY RS_Date
              )
SELECT *,SUM(CT) OVER(ORDER BY RS_Date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS Run_CT
FROM cte

演示:SQL Fiddle

如果在 2012 年之前无法使用某些东西,您可以使用:

;with cte AS (SELECT RS_Date
                    ,COUNT(DISTINCT M_ID) AS CT
              FROM Table1
              GROUP BY RS_Date
              )
SELECT a.RS_Date
      ,SUM(b.CT)
FROM cte a
LEFT JOIN cte b
  ON a.RS_DAte >= b.RS_Date
GROUP BY a.RS_Date  

演示:SQL Fiddle

看起来你想要这样的东西:

SELECT
  RS_Date,
  SUM(c) OVER (PARTITION BY M_StartDate ORDER BY RS_Date ROWS UNBOUNDED PRECEEDING)
FROM
  (
    SELECT M_StartDate, RS_Date, COUNT(DISTINCT M_Id) AS c
    FROM my_table
    GROUP BY M_StartDate, RS_Date
  ) counts

内联视图计算每个 (M_StartDate, RS_Date) 组中不同 M_Id 值的计数(仅在组内强制执行不同),外部查询使用SUM() 的分析版本将每个 M_StartDate.

中的计数相加

请注意,此特定查询不会完全重现您的示例结果。它会产生:

RS_Date   Active
-----------------
1/1/2014    5
1/5/2014    7
3/2/2014    8
3/2/2014    2

这是因为您的示例数据中某些行 RS_Date 3/2/2014 比其他行 M_StartDate 晚。如果这不是你想要的那么你需要澄清这个问题,目前看起来有点不一致。

不幸的是,分析功能直到 SQL Server 2012 才可用。在 SQL Server 2010 中,工作更加混乱。可以这样做:

WITH gc AS (
  SELECT M_StartDate, RS_Date, COUNT(DISTINCT M_Id) AS c
  FROM my_table
  GROUP BY M_StartDate, RS_Date
)
SELECT
  RS_Date,
  (
    SELECT SUM(c)
    FROM gc2
    WHERE gc2.M_StartDate = gc.M_StartDate AND gc2.RS_Date <= gc.RS_Date
  ) AS Active
FROM gc