这适用于SQL Server 2008/2012。

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

如果服务中断,例如ID为1002的成员,其声明的结束日期为05/15,下一个开始于05/18,则计数应重新开始。

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和我也尝试了下表,以首先获取声明之间的所有日期。但是我在计算连续日期之间的天数时遇到问题,如果覆盖范围中断,则无法重新设置计数。

Master.dbo.spt_values


任何帮助表示赞赏。谢谢!

最佳答案

您需要首先找到差距。

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

现在您有了差距,现在可以使用GROUP BY生成MIN(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

10-06 12:45