【问题标题】:Running total of records based on date ranges in t-sql根据 t-sql 中的日期范围运行记录总数
【发布时间】:2014-03-11 15:58:49
【问题描述】:

样本数据:

groupID CustomerID  CustomerAddr    work_date   work_order
CA123   ABC12345    123 MAIN ST     2/1/2012    WORKNEW
CA123   ABC12345    123 MAIN ST     10/9/2012   ZZZ888
CA123   ABC12345    123 MAIN ST     3/9/2013    ZZZ131
WA999   ZZZ99909    451 EAST ST     1/13/2013   SY1234
WA999   ZZZ99909    451 EAST ST     4/15/2013   WORKOTHER
WA999   ZZZ99909    451 EAST ST     5/17/2013   SY1244
WA999   ZZZ99909    451 EAST ST     12/8/2013   SY1334
CA123   ABD54321    522 AVE A       4/21/2013   WW9999

对于给定的示例数据,我需要计算具有相同 groupID 和 CustomerID 的记录在 6、12 和 18 个月的时间间隔内出现了多少次。该计数应独立于具有相同 groupID 和 customerID 的其他记录。

输出应该是这样的:

groupID CustomerID  work_date   six_month_count twelve_month_count  twenty_four_month_count
CA123   ABC12345    2/1/2012    0               1                   2
CA123   ABC12345    10/9/2012   1               1                   1
CA123   ABC12345    3/9/2013    0               0                   0
WA999   ZZZ99909    1/13/2013   2               3                   3               
WA999   ZZZ99909    4/15/2013   1               2                   2
WA999   ZZZ99909    5/17/2013   0               1                   1
WA999   ZZZ99909    12/8/2013   0               0                   0
CA123   ABD54321    4/21/2013   0               0                   0

我唯一能想到的就是获取每行的当前记录和最大记录,但我不知道如何计算给定范围的记录。

任何帮助将不胜感激。

【问题讨论】:

  • 如何定义 6、12 和 18 个月的间隔?

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


【解决方案1】:

您可以将表连接到自身,然后通过聚合计算出 6,12 和 24 列。我使用Work_Order 作为键来避免在自我加入期间计算记录与自身。

WITH cteCountInRange
AS
(
    SELECT c1.CustomerID, 
           c1.GroupID, 
           c1.Work_Date as WorkDate1, 
           c2.Work_Date as WorkDate2, 
           CASE WHEN c2.Work_Date > c1.Work_Date AND c1.Work_Order <> c2.Work_Order 
                THEN 1 
                ELSE 0 
           END AS Eligible,
           DATEDIFF(M, c1.Work_Date, c2.Work_Date ) AS MonthsDiff
    FROM CustomerData c1 INNER JOIN CustomerData c2
        ON c1.CustomerID = c2.CustomerID AND c1.GroupID = c2.GroupID
)
SELECT cir.CustomerID, cir.GroupID, cir.WorkDate1, 
    SUM(CASE WHEN Eligible = 1 AND MonthsDiff <= 6 THEN 1 ELSE 0 END) AS SixMonthCount,
    SUM(CASE WHEN Eligible = 1 AND MonthsDiff <= 12 THEN 1 ELSE 0 END) AS TwelveMonthCount,
    SUM(CASE WHEN Eligible = 1 AND MonthsDiff <= 24 THEN 1 ELSE 0 END) AS TwentyFourMonthCount
FROM cteCountInRange cir
GROUP BY cir.CustomerID, cir.GroupID, cir.WorkDate1;

Fiddle here

编辑
附加注释 - 我们无法在 CTE 中过滤掉“InEligible”行的原因是,如果在当前行之后没有其他匹配行,则需要一行 ZEROES。如果我们过滤这些,我们需要另一个 LEFT JOIN 回到原始表以包含零行。

【讨论】:

  • 这看起来很棒并且适用于我的问题。我有一个我之前省略的额外请求:是否可以计算唯一的“客户”(groupid/customerid,省略 work_order)并将项目保留在原位还是需要单独查询?这样做的原因是同一个月可能有多次“访问”,但我还需要一个真/假值来表示客户在每个时间段(6 个月等)的访问。这甚至可能吗?如果我需要澄清,我可以添加到原来的问题,甚至打开一个单独的问题。
猜你喜欢
  • 2013-06-23
  • 1970-01-01
  • 2015-06-11
  • 1970-01-01
  • 1970-01-01
  • 2021-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多