延长结束日期,然后重复比较

时间:2018-11-15 16:06:45

标签: sql sql-server loops

我想做的是扩展RxEndDates直到处方中不再有重叠。而且新的扩展名也不会重叠。

上下文:如果Amy每天服用Humera并在其当前处方用完之前得到补充,则将第二个处方的DaySupply添加到第一个处方中。

sample data:
User Drug   RxStartDate DaySupply   RxEndDate
Amy Humera  2/12/2017   7   2/18/2017
Amy Humera  2/28/2017   5   3/4/2017 <--Overlap with below
Amy Humera  3/3/2017    5   3/7/2017 <--Overlap with above, need to combine
Amy Humera  3/8/2017    2   3/9/2017
Amy Humera  3/10/2017   7   3/16/2017
Amy Humera  3/17/2017   30  4/15/2017 <--Overlap with all below, combine
Amy Humera  3/22/2017   2   3/23/2017 <--Overlap
Amy Humera  3/24/2017   2   3/25/2017 <--Overlap
Amy Humera  3/31/2017   3   4/2/2017  <--Overlap
Amy Humera  4/7/2017    5   4/11/2017 <--Overlap
Amy Humera  4/13/2017   30  5/12/2017 <--Overlap

所以我们合并后,我们得到了

User Drug   RxStartDate DaySupply   RxEndDate
Amy Humera  2/12/2017   7   2/18/2017
Amy Humera  2/28/2017   10  3/9/2017 <-- Combined from above, new overlap
Amy Humera  3/8/2017    2   3/9/2017 <-- Now this overlaps with above
Amy Humera  3/10/2017   7   3/16/2017
Amy Humera  3/17/2017   72  5/27/2017

User Drug   RxStartDate DaySupply   RxEndDate
Amy Humera  2/12/2017   7   2/18/2017
Amy Humera  2/28/2017   12  3/11/2017 <-- Combined, again, new overlap
Amy Humera  3/10/2017   7   3/16/2017 <-- Now this overlaps with above
Amy Humera  3/17/2017   72  5/27/2017

User Drug   RxStartDate DaySupply   RxEndDate
Amy Humera  2/12/2017   7   2/18/2017
Amy Humera  2/28/2017   19  3/18/2017 <-- Combined, again, new overlap
Amy Humera  3/17/2017   72  5/27/2017 <-- Now this overlaps with above

User Drug   RxStartDate DaySupply   RxEndDate
Amy Humera  2/12/2017   7   2/18/2017
Amy Humera  2/28/2017   91  5/29/2017
There is no more overlap…finished!     

有没有一种方法可以自动循环执行?

3 个答案:

答案 0 :(得分:0)

您可以使用not exists来确定组的起始位置。然后做一个累加和分配一个组。 。 。和聚合。以下假设一个唯一的id,这是处理重复项所必需的:

select [user], drug, grp, sum(daysupply), min(RxStartDate), max(RxEndDate)
    from (select t.*, sum(flg) over (partition by [user], drug order by RxStartDate) as grp
          from (select t.*,
                       (case when exists (select 1
                                          from @test t2
                                          where t2.[user] = t.[user] and t2.drug = t.drug and
                                                t2.RxStartDate < t.RxStartDate and
                                                t2.RxEndDate >= dateadd(day, -1, t.RxStartDate)
                                         )
                             then 0 else 1
                        end) as flg
                from @test t
               ) t
          ) t
    group by [user], drug, grp;

答案 1 :(得分:0)

我使用了CTE Common Table Expression来进行分组。由于某些日子在技术上不会重叠,因此我通过在[RxEndDate_ALT]中的[RxEndDate]上加1来创建备用结束日期source_data。然后,我可以使用NOT EXISTS中的source_data_grouped对日期进行分组。之后,我回到source_data_rawSUM的{​​{1}}。


结果

screenshot


SQL

[DaySupply]

答案 2 :(得分:0)

我认为该解决方案只能通过递归来实现,因为应该有一个循环来计算累积的DaySupply,并且我看不到任何非递归查找都可以做到这一点。您可以使用递归CTE进行此操作-根据官方文档,此功能可从SQL Server 2008开始使用。
一个可能的实现(我添加了一些测试数据来挑战它):

DECLARE @test TABLE (
    [User] VARCHAR(100),
    Drug VARCHAR(100),
    RxStartDate DATE,
    DaySupply INT,
    RxEndDate DATE
)

INSERT @test
VALUES
    ('Amy', 'Humera', '2/12/2017', '7', '2/18/2017'),
    ('Amy', 'Humera', '2/28/2017', '5', '3/4/2017'),
    ('Amy', 'Humera', '3/3/2017', '5', '3/7/2017'),
    ('Amy', 'Humera', '3/8/2017', '2', '3/9/2017'),
    ('Amy', 'Humera', '3/10/2017', '7', '3/16/2017'),
    ('Amy', 'Humera', '3/17/2017', '30', '4/15/2017'),
    ('Amy', 'Humera', '3/22/2017', '2', '3/23/2017'),
    ('Amy', 'Humera', '3/24/2017', '2', '3/25/2017'),
    ('Amy', 'Humera', '3/31/2017', '3', '4/2/2017'),
    ('Amy', 'Humera', '4/7/2017', '5', '4/11/2017'),
    ('Amy', 'Humera', '4/13/2017', '30', '5/12/2017'),

    ('Amy', 'Other', '3/24/2017', '7', '3/30/2017'),
    ('Amy', 'Other', '3/31/2017', '3', '4/2/2017'),
    ('Amy', 'Other', '4/7/2017', '5', '4/11/2017'),
    ('Amy', 'Other', '4/13/2017', '30', '5/12/2017'),

    ('Joe', 'Humera', '3/24/2017', '8', '3/31/2017'),
    ('Joe', 'Humera', '3/31/2017', '3', '4/2/2017'),
    ('Joe', 'Humera', '4/12/2017', '5', '4/16/2017'),
    ('Joe', 'Humera', '4/23/2017', '30', '5/22/2017'),

    ('Joe', 'Other', '3/24/2017', '60', '5/23/2017'),
    ('Joe', 'Other', '3/31/2017', '3', '4/2/2017'),
    ('Joe', 'Other', '4/7/2017', '5', '4/11/2017'),
    ('Joe', 'Other', '4/13/2017', '30', '5/12/2017')



-- You can comment this out, it is just to show progress:
SELECT * FROM @test ORDER BY [User], Drug, RxStartDate



DECLARE @test_2 TABLE (
    [User] VARCHAR(100),
    Drug VARCHAR(100),
    RxStartDate_base DATE,
    DaySupplyCumulative INT
)

;WITH CTE_RxEndDateExtended as (
    SELECT [User], Drug, RxStartDate, DaySupply, DaySupply as DaySupplyCumulative, RxStartDate as RxStartDate_base, RxStartDate as RxStartDateExtended, dateadd (dd, DaySupply, RxStartDate) as RxEndDateExtended
    FROM @test
    -- WHERE [User] = 'Amy' and Drug = 'Humera' and RxStartDate = '2/28/2017'
    UNION ALL
    SELECT t.[User], t.Drug, t.RxStartDate, t.DaySupply, c.DaySupplyCumulative + t.DaySupply as DaySupplyCumulative, c.RxStartDate_base, t.RxStartDate as RxStartDateExtended, dateadd (dd, t.DaySupply, c.RxEndDateExtended) as RxEndDateExtended
    FROM CTE_RxEndDateExtended as c INNER JOIN @test as t
        on c.[User] = t.[User] and c.Drug = t.Drug
            and c.RxEndDateExtended >= t.RxStartDate and c.RxStartDateExtended < t.RxStartDate
)
INSERT @test_2
SELECT [User], Drug, RxStartDate_base, MAX (DaySupplyCumulative) as DaySupplyCumulative -- comment this out and use this for debugging: SELECT *
FROM CTE_RxEndDateExtended
GROUP BY [User], Drug, RxStartDate_base -- comment this out for debugging
OPTION (MAXRECURSION 0) -- comment this out and use this for debugging (to avoid infinite loops): OPTION (MAXRECURSION 1000)



-- You can comment this out, it is just to show progress:
SELECT * FROM @test_2
ORDER BY [User], Drug, RxStartDate_base -- comment this out and use this for debugging: ORDER BY [User], Drug, RxStartDate_base, RxStartDate, DaySupplyCumulative



SELECT base.*, dateadd (dd, base.DaySupplyCumulative - 1, base.RxStartDate_base) as RxEndDateCumulative
FROM @test_2 as base LEFT OUTER JOIN @test_2 as filter
    on base.[User] = filter.[User] and base.Drug = filter.Drug
        and base.RxStartDate_base > filter.RxStartDate_base
        and dateadd (dd, base.DaySupplyCumulative, base.RxStartDate_base) <= dateadd (dd, filter.DaySupplyCumulative, filter.RxStartDate_base)
WHERE filter.[User] IS NULL
ORDER BY [User], Drug, RxStartDate_base

也许您需要通过简化逻辑对其进行优化。但是请注意不要造成无限循环。调试时,请使用OPTION(MAXRECURSION N )和 N 而不是零。

PS .:如果我添加“ Amy”,“ Humera”,“ 2/15/2017”,“ 11”,“ 2/25/2017”,这也是可行的,我批评了其他解决方案。 ..我很好奇它是否按预期工作-请进行测试!