计算多行的最大连续月数

时间:2014-03-10 15:47:08

标签: sql sql-server

我正在尝试计算表格中跨越多行开始日期结束日期的最大连续月数。日期范围不需要完全连续,只需要连续几个月。例如,如果客户的日期范围为01/01/2012 - 06/01/2012和07/01/2012 - 08/31/2012,那么我们将计算6月和7月,结果连续8个月。

示例数据如下。

基本表 CustomerID StartDate EndDate ---------- ---------- ---------- 1001 01/01/2012 06/30/2012 1001 07/01/2012 08/31/2012 1001 01/01/2013 07/31/2013 1002 01/01/2012 06/01/2012 1002 07/01/2012 08/31/2012 1003 01/01/2012 05/31/2012 1003 07/01/2012 08/31/2012 1004 01/01/2012 02/28/2012 1004 03/01/2012 07/31/2012 1004 08/01/2012 08/31/2012

结果 CustomerID MaxContinuous ---------- ------------- 1001 8 1002 8 1003 5 1004 8

应该可以创建一个子表,每个月都涉及一个循环,然后遍历该表寻找连续几个月,但这涉及两个循环,我宁愿避免。

1 个答案:

答案 0 :(得分:3)

如果自定义无法重叠日期,则此问题很容易。首先是每个记录看看我们有多少个月:

 SELECT CustomerID, ABS(DATEDIFF('MONTH',StartDate,EndDate)) as Months 
 FROM BaseData

然后获得最大值

 SELECT CustomeID, MAX(Months) AS MaxContig
 FROM (
   SELECT CustomerID, ABS(DATEDIFF('MONTH',StartDate,EndDate)) as Months 
   FROM BaseData
 ) sub

由于受欢迎的需求,这里是如何使用递归CTE - 请注意,此代码建立在上面的代码之前,因此在您潜入之前了解。您还必须知道递归CTE如何工作。

WITH rangeList AS
 (
   SELECT CustomerID,
          StartDate, 
          EndDate,
          DATEDIFF(month,StartDate,EndDate)+1 as Months 
   FROM Customers

   UNION ALL

   SELECT R.CustomerID, 
          R.StartDate,
          BD.EndDate,
          DATEDIFF(month,R.StartDate,BD.EndDate)+1 as Months 
   FROM rangeList R
   JOIN Customers BD 
     ON R.CustomerID = BD.CustomerID AND
        Month(DATEADD(month,1,R.EndDate)) = Month(BD.StartDate) AND
        Year(DATEADD(month,1,R.EndDate)) = Year(BD.StartDate)
 )
 SELECT CustomerID, Max(Months) as MaxContig
 FROM rangeList
 GROUP BY CustomerID

小提琴:http://sqlfiddle.com/#!6/eee59/14

关于此解决方案的一些注意事项

  • startdate必须在enddate之前(可以更改以修复此问题)
  • 日期不得重叠(可以更改以解决此问题)
  • 你可能需要玩连接,因为这取决于你的规格......正如所指出的,如果开始和结束日期是在同一个月,这将不起作用 - 但也许它们应该?但请记住要小心,使用无限递归的stackoverflow很容易。