Sql server 获取跨多行的天数计数

Sql server 获取跨多行的天数计数,sql-server,sql-server-2008,date,sql-server-2012,Sql Server,Sql Server 2008,Date,Sql Server 2012,这是针对SQL Server 2008/2012的 我有以下带有索赔开始日期和结束日期的数据集。我想计算连续索赔的天数,其中下一个日期的索赔开始日期比上一个日期的索赔结束日期晚一天,使其成为连续服务 如果服务中断,如会员id 1002,其中索赔于2015年5月5日结束,下一次索赔于2018年5月5日开始,则计数应重新开始 MemberID Claim Start Claim End Claim_ID 1001 2016-04-01 2016-04-15

这是针对SQL Server 2008/2012的

我有以下带有索赔开始日期和结束日期的数据集。我想计算连续索赔的天数,其中下一个日期的索赔开始日期比上一个日期的索赔结束日期晚一天,使其成为连续服务

如果服务中断,如会员id 1002,其中索赔于2015年5月5日结束,下一次索赔于2018年5月5日开始,则计数应重新开始

MemberID    Claim Start   Claim End      Claim_ID
1001        2016-04-01    2016-04-15     ABC11111
1001        2016-04-16    2016-04-30     ABC65465
1001        2016-05-01    2016-05-15     ABC51651
1001        2016-05-16    2016-06-15     ABC76320
1002        2016-04-01    2016-04-15     ABC74563
1002        2016-04-16    2016-04-30     ABC02123
1002        2016-05-01    2016-05-15     ABC02223
1002        2016-05-18    2016-06-15     ABC66632
1002        2016-06-16    2016-06-30     ABC77447
1002        2016-07-10    2016-07-31     ABC33221
1002        2016-08-01    2016-08-10     ABC88877
因此,实际上,我希望得到以下输出。第一次索赔开始日期的最小值,当多个索赔之间的保险范围没有差距时,索赔结束日期的最大值。如果保险范围存在缺口,则重新开始计数,并计算第一次索赔开始日期的最小值和索赔结束日期的最大值,直到多个索赔之间的保险范围没有缺口为止

MemberID    Claim_Start   Claim_End     Continuous_Service_Days
1001        2016-04-01    2016-06-15    76
1002        2016-04-01    2016-05-15    45
1002        2016-05-18    2016-06-30    44 
1002        2016-07-10    2016-08-10    32
我尝试了while loops、CTE和我也尝试了下表,以首先获得索赔之间的所有日期。但我在计算连续日期之间的天数时遇到了问题,如果保险范围出现中断,则需要重新设置计数

Master.dbo.spt_values

感谢您的帮助。谢谢

你需要先找到差距

此解决方案使用生成从ClaimStart到ClaimEnd的第一个日期。然后使用生成的日期,使用获取间隙

现在您已经有了间隙,现在可以使用GROUP BY来设置MINClaimStart和MAXClaimStart:

返回

MemberID    Claim Start Claim End   Continuous_Service_Days
1001        2016-04-01  2016-06-15  76
1002        2016-04-01  2016-05-15  45
1002        2016-05-18  2016-06-30  44
1002        2016-07-10  2016-08-10  32

我认为您应该首先检测并标记有间隙的行。我试图回答,然后发现这是一个间隙问题。没那么简单。退房这很有帮助。窗口功能是我们在这类问题上的朋友。这太神奇了。工作完美。然而,我下一步要做的是了解到底发生了什么。在我的脑海里,我仍在解密这段美妙的代码。谢谢你的帮助@SanketJ阅读了我答案中链接的两篇文章。这两种方法都读得很好,略有不同,但这一种也很好用。你能不能也提供一些我可以参考的文章来了解你是如何获得这些CTE的?@SanketJ cteMinMax只是获取了所需的最小/最大日期。。。如果您有固定的开始日期,则不需要。cte0是一个10整数的虚拟表。cteDates将cte0扩展到100000行,然后将这些行转换为日期。我们现在有了一个完整的连续日期列表,带有一个行号。Grp现在获取这个RN-your表行,它将创建一个组序列。期末考试在哪里适用aggregations@SanketJ简言之,我的最佳建议是运行增量CTE以查看每个CTE与前一个CTE的关系,然后在最终选择中运行子查询以更好地可视化流程
Declare @YourTable table (MemberID int,[Claim Start] date,[Claim End] date,[Claim_ID] varchar(25))
Insert Into @YourTable values
(1001,'2016-04-01','2016-04-15','ABC11111'),
(1001,'2016-04-16','2016-04-30','ABC65465'),
(1001,'2016-05-01','2016-05-15','ABC51651'),
(1001,'2016-05-16','2016-06-15','ABC76320'),
(1002,'2016-04-01','2016-04-15','ABC74563'),
(1002,'2016-04-16','2016-04-30','ABC02123'),
(1002,'2016-05-01','2016-05-15','ABC02223'),
(1002,'2016-05-18','2016-06-15','ABC66632'),
(1002,'2016-06-16','2016-06-30','ABC77447'),
(1002,'2016-07-10','2016-07-31','ABC33221'),
(1002,'2016-08-01','2016-08-10','ABC88877')


;with cte0(N)   as (Select 1 From (Values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N(N))
     ,cte1(R,D) as (Select Row_Number() over (Order By (Select Null))
                          ,DateAdd(DD,-1+Row_Number() over (Order By (Select Null)),(Select MinDate=min([Claim Start]) From  @YourTable)) 
                     From  cte0 N1, cte0 N2, cte0 N3, cte0 N4) 
Select MemberID
      ,[Claim Start] = Min([Claim Start])
      ,[Claim End]   = Max([Claim End])
      ,Continuous_Service_Days = count(*)
 From (
         Select *,Island = R - Row_Number() over (Partition By MemberID Order by [Claim Start])
          From  @YourTable A
          Join  cte1   B on D Between [Claim Start] and [Claim End]
      ) A
 Group By MemberID,Island
 Order By 1,2
MemberID    Claim Start Claim End   Continuous_Service_Days
1001        2016-04-01  2016-06-15  76
1002        2016-04-01  2016-05-15  45
1002        2016-05-18  2016-06-30  44
1002        2016-07-10  2016-08-10  32