获取多行的天数

时间:2016-11-14 21:23:32

标签: sql-server sql-server-2008 date sql-server-2012

这适用于SQL Server 2008/2012。

我有以下数据集,其中包含声明开始日期和结束日期。我想计算背靠背索赔的天数,其中下一个日期的索赔开始日期是在上一个日期的索赔结束日期之后的一天,使其成为连续服务。

如果服务中断,例如05/15的索赔结束和05/18开始的会员ID 1002,计数应该重新启动。

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循环,CTE&s,我也尝试了下表,首先获得声明之间的所有日期。但我在计算连续日期之间的天数方面遇到问题,如果覆盖范围中断,则重置计数。

Master.dbo.spt_values

感谢任何帮助。谢谢!

2 个答案:

答案 0 :(得分:2)

您需要先找到差距。

此解决方案使用Tally Table生成从ClaimStartClaimEnd的日期。然后使用生成的日期,使用this method获取差距。

现在您已经有了差距,现在可以使用GROUP BYMIN(ClaimStart)和MAX(ClaimStart)

WITH E1(N) AS( -- 10 ^ 1 = 10 rows
    SELECT 1 FROM(VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))t(N)
),
E2(N) AS(SELECT 1 FROM E1 a CROSS JOIN E1 b), -- 10 ^ 2 = 100 rows
E4(N) AS(SELECT 1 FROM E2 a CROSS JOIN E2 b), -- 10 ^ 4 = 10,000 rows
CteTally(N) AS(
    SELECT TOP(SELECT MAX(DATEDIFF(DAY, ClaimStart, ClaimEnd) + 1) FROM tbl) 
        ROW_NUMBER() OVER(ORDER BY(SELECT NULL))
    FROM E4
),
CteDates AS( -- Generate the dates from ClaimStart to ClaimEnd
    SELECT
        t.MemberID,
        dt = DATEADD(DAY, ct.N - 1, t.ClaimStart)
    FROM tbl t
    INNER JOIN CteTally ct
        ON DATEADD(DAY, ct.N - 1, t.ClaimStart) <= t.ClaimEnd
),
CteGrp AS( -- Find gaps and continuous dates
    SELECT *,
        rn = DATEADD(DAY, - ROW_NUMBER() OVER(PARTITION BY MemberID ORDER BY dt), dt)
    FROM CteDates
)
SELECT
    MemberID,
    ClaimStart  = MIN(dt),
    ClaimEnd    = MAX(dt),
    Diff        = DATEDIFF(DAY, MIN(dt), MAX(dt)) + 1
FROM CteGrp
GROUP BY MemberID, rn
ORDER BY MemberID, ClaimStart;

ONLINE DEMO

答案 1 :(得分:1)

void *j;
cudaMalloc(&j, sizeof(int*)*N); // stores result in j
int **devicePointersStoredInDeviceMemory = (int **) j;

返回

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