Convert Over-Lapping Date Ranges To Rows of Date Ranges










0















I have a list of Date Ranges in a table that can be open ended (enddate = null):



Index startdate enddate
1 2018-07-13 NULL
2 2018-11-14 2018-11-16
3 2018-11-15 2018-11-15


Query for Test Data:



DECLARE @ScheduleTable Table([Index] int not null, StartDate DateTime not null, EndDate DateTime null)
insert into @ScheduleTable ([Index], StartDate, EndDate)
values
(1,'2018-07-13',null)
, (2,'2018-11-14','2018-11-16')
, (3,'2018-11-15','2018-11-15')
select*from @ScheduleTable


How can I write a query that will "fill in the holes" and return the following results:



Index startdate enddate
1 2018-07-13 2018-11-13
2 2018-11-14 2018-11-14
3 2018-11-15 2018-11-15
2 2018-11-16 2018-11-16
1 2018-11-17 NULL


Query displaying expected results:



select 
1 as [Index], '2018-07-13' as StartDate, '2018-11-13' as EndDate
UNION ALL
select
2 as [Index], '2018-11-14', '2018-11-14'
UNION ALL
select
3 as [Index], '2018-11-15', '2018-11-15'
UNION ALL
select
2 as [Index], '2018-11-16', '2018-11-16'
UNION ALL
select
1 as [Index], '2018-11-17', null






I'd prefer an answer that doesn't involve parameters/ temp table etc. I have a Date Dimension table if that would help.



In the above example, the entry with Index=1 is open-ended and starts on 7.13. It is interrupted by Index=2 on 11.14. Index=2 is then interrupted by Index=3 on 11.15. Index=2 then starts again on 11.16. Followed by Index=1 starting up again on 11.17

The Index determines the order of preference, so Index=2 will override Index=1 on 11.14 - 11.16 and Index=3 will override Index=2 on 11.15.



Here is my current query using lead():



DECLARE @MinDate DateTime = '2015-01-01'
DECLARE @MaxDate DateTime = '2020-01-01'

select
row_number() over(partition by dealid order by ss.StartDate, ss.id) as [Index]
, ss.startdate
, ss.enddate
, case when ss.enddate is null then
dateadd(d,-1,lead(ss.startdate,1,@MaxDate) over(partition by dealid order by ss.startdate, ss.id))
else ss.enddate end
as EndDate
from
[dbo].[Schedule]ss
where ss.enabled = 1









share|improve this question



















  • 1





    What's the logic between sample data and expect result?

    – D-Shih
    Nov 12 '18 at 16:59











  • Can the date ranges overlap? If yes, what should be returned if they do?

    – Zohar Peled
    Nov 12 '18 at 17:02











  • Sample data is best served as DDL + DML. Please edit your question to include it, your current attempt and your desired results. For more details, read this.

    – Zohar Peled
    Nov 12 '18 at 17:10











  • Can you have more than one record with null as endDate?

    – Zohar Peled
    Nov 12 '18 at 19:43















0















I have a list of Date Ranges in a table that can be open ended (enddate = null):



Index startdate enddate
1 2018-07-13 NULL
2 2018-11-14 2018-11-16
3 2018-11-15 2018-11-15


Query for Test Data:



DECLARE @ScheduleTable Table([Index] int not null, StartDate DateTime not null, EndDate DateTime null)
insert into @ScheduleTable ([Index], StartDate, EndDate)
values
(1,'2018-07-13',null)
, (2,'2018-11-14','2018-11-16')
, (3,'2018-11-15','2018-11-15')
select*from @ScheduleTable


How can I write a query that will "fill in the holes" and return the following results:



Index startdate enddate
1 2018-07-13 2018-11-13
2 2018-11-14 2018-11-14
3 2018-11-15 2018-11-15
2 2018-11-16 2018-11-16
1 2018-11-17 NULL


Query displaying expected results:



select 
1 as [Index], '2018-07-13' as StartDate, '2018-11-13' as EndDate
UNION ALL
select
2 as [Index], '2018-11-14', '2018-11-14'
UNION ALL
select
3 as [Index], '2018-11-15', '2018-11-15'
UNION ALL
select
2 as [Index], '2018-11-16', '2018-11-16'
UNION ALL
select
1 as [Index], '2018-11-17', null






I'd prefer an answer that doesn't involve parameters/ temp table etc. I have a Date Dimension table if that would help.



In the above example, the entry with Index=1 is open-ended and starts on 7.13. It is interrupted by Index=2 on 11.14. Index=2 is then interrupted by Index=3 on 11.15. Index=2 then starts again on 11.16. Followed by Index=1 starting up again on 11.17

The Index determines the order of preference, so Index=2 will override Index=1 on 11.14 - 11.16 and Index=3 will override Index=2 on 11.15.



Here is my current query using lead():



DECLARE @MinDate DateTime = '2015-01-01'
DECLARE @MaxDate DateTime = '2020-01-01'

select
row_number() over(partition by dealid order by ss.StartDate, ss.id) as [Index]
, ss.startdate
, ss.enddate
, case when ss.enddate is null then
dateadd(d,-1,lead(ss.startdate,1,@MaxDate) over(partition by dealid order by ss.startdate, ss.id))
else ss.enddate end
as EndDate
from
[dbo].[Schedule]ss
where ss.enabled = 1









share|improve this question



















  • 1





    What's the logic between sample data and expect result?

    – D-Shih
    Nov 12 '18 at 16:59











  • Can the date ranges overlap? If yes, what should be returned if they do?

    – Zohar Peled
    Nov 12 '18 at 17:02











  • Sample data is best served as DDL + DML. Please edit your question to include it, your current attempt and your desired results. For more details, read this.

    – Zohar Peled
    Nov 12 '18 at 17:10











  • Can you have more than one record with null as endDate?

    – Zohar Peled
    Nov 12 '18 at 19:43













0












0








0








I have a list of Date Ranges in a table that can be open ended (enddate = null):



Index startdate enddate
1 2018-07-13 NULL
2 2018-11-14 2018-11-16
3 2018-11-15 2018-11-15


Query for Test Data:



DECLARE @ScheduleTable Table([Index] int not null, StartDate DateTime not null, EndDate DateTime null)
insert into @ScheduleTable ([Index], StartDate, EndDate)
values
(1,'2018-07-13',null)
, (2,'2018-11-14','2018-11-16')
, (3,'2018-11-15','2018-11-15')
select*from @ScheduleTable


How can I write a query that will "fill in the holes" and return the following results:



Index startdate enddate
1 2018-07-13 2018-11-13
2 2018-11-14 2018-11-14
3 2018-11-15 2018-11-15
2 2018-11-16 2018-11-16
1 2018-11-17 NULL


Query displaying expected results:



select 
1 as [Index], '2018-07-13' as StartDate, '2018-11-13' as EndDate
UNION ALL
select
2 as [Index], '2018-11-14', '2018-11-14'
UNION ALL
select
3 as [Index], '2018-11-15', '2018-11-15'
UNION ALL
select
2 as [Index], '2018-11-16', '2018-11-16'
UNION ALL
select
1 as [Index], '2018-11-17', null






I'd prefer an answer that doesn't involve parameters/ temp table etc. I have a Date Dimension table if that would help.



In the above example, the entry with Index=1 is open-ended and starts on 7.13. It is interrupted by Index=2 on 11.14. Index=2 is then interrupted by Index=3 on 11.15. Index=2 then starts again on 11.16. Followed by Index=1 starting up again on 11.17

The Index determines the order of preference, so Index=2 will override Index=1 on 11.14 - 11.16 and Index=3 will override Index=2 on 11.15.



Here is my current query using lead():



DECLARE @MinDate DateTime = '2015-01-01'
DECLARE @MaxDate DateTime = '2020-01-01'

select
row_number() over(partition by dealid order by ss.StartDate, ss.id) as [Index]
, ss.startdate
, ss.enddate
, case when ss.enddate is null then
dateadd(d,-1,lead(ss.startdate,1,@MaxDate) over(partition by dealid order by ss.startdate, ss.id))
else ss.enddate end
as EndDate
from
[dbo].[Schedule]ss
where ss.enabled = 1









share|improve this question
















I have a list of Date Ranges in a table that can be open ended (enddate = null):



Index startdate enddate
1 2018-07-13 NULL
2 2018-11-14 2018-11-16
3 2018-11-15 2018-11-15


Query for Test Data:



DECLARE @ScheduleTable Table([Index] int not null, StartDate DateTime not null, EndDate DateTime null)
insert into @ScheduleTable ([Index], StartDate, EndDate)
values
(1,'2018-07-13',null)
, (2,'2018-11-14','2018-11-16')
, (3,'2018-11-15','2018-11-15')
select*from @ScheduleTable


How can I write a query that will "fill in the holes" and return the following results:



Index startdate enddate
1 2018-07-13 2018-11-13
2 2018-11-14 2018-11-14
3 2018-11-15 2018-11-15
2 2018-11-16 2018-11-16
1 2018-11-17 NULL


Query displaying expected results:



select 
1 as [Index], '2018-07-13' as StartDate, '2018-11-13' as EndDate
UNION ALL
select
2 as [Index], '2018-11-14', '2018-11-14'
UNION ALL
select
3 as [Index], '2018-11-15', '2018-11-15'
UNION ALL
select
2 as [Index], '2018-11-16', '2018-11-16'
UNION ALL
select
1 as [Index], '2018-11-17', null






I'd prefer an answer that doesn't involve parameters/ temp table etc. I have a Date Dimension table if that would help.



In the above example, the entry with Index=1 is open-ended and starts on 7.13. It is interrupted by Index=2 on 11.14. Index=2 is then interrupted by Index=3 on 11.15. Index=2 then starts again on 11.16. Followed by Index=1 starting up again on 11.17

The Index determines the order of preference, so Index=2 will override Index=1 on 11.14 - 11.16 and Index=3 will override Index=2 on 11.15.



Here is my current query using lead():



DECLARE @MinDate DateTime = '2015-01-01'
DECLARE @MaxDate DateTime = '2020-01-01'

select
row_number() over(partition by dealid order by ss.StartDate, ss.id) as [Index]
, ss.startdate
, ss.enddate
, case when ss.enddate is null then
dateadd(d,-1,lead(ss.startdate,1,@MaxDate) over(partition by dealid order by ss.startdate, ss.id))
else ss.enddate end
as EndDate
from
[dbo].[Schedule]ss
where ss.enabled = 1






tsql datetime






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 12 '18 at 19:12







RIanGillis

















asked Nov 12 '18 at 16:55









RIanGillisRIanGillis

391210




391210







  • 1





    What's the logic between sample data and expect result?

    – D-Shih
    Nov 12 '18 at 16:59











  • Can the date ranges overlap? If yes, what should be returned if they do?

    – Zohar Peled
    Nov 12 '18 at 17:02











  • Sample data is best served as DDL + DML. Please edit your question to include it, your current attempt and your desired results. For more details, read this.

    – Zohar Peled
    Nov 12 '18 at 17:10











  • Can you have more than one record with null as endDate?

    – Zohar Peled
    Nov 12 '18 at 19:43












  • 1





    What's the logic between sample data and expect result?

    – D-Shih
    Nov 12 '18 at 16:59











  • Can the date ranges overlap? If yes, what should be returned if they do?

    – Zohar Peled
    Nov 12 '18 at 17:02











  • Sample data is best served as DDL + DML. Please edit your question to include it, your current attempt and your desired results. For more details, read this.

    – Zohar Peled
    Nov 12 '18 at 17:10











  • Can you have more than one record with null as endDate?

    – Zohar Peled
    Nov 12 '18 at 19:43







1




1





What's the logic between sample data and expect result?

– D-Shih
Nov 12 '18 at 16:59





What's the logic between sample data and expect result?

– D-Shih
Nov 12 '18 at 16:59













Can the date ranges overlap? If yes, what should be returned if they do?

– Zohar Peled
Nov 12 '18 at 17:02





Can the date ranges overlap? If yes, what should be returned if they do?

– Zohar Peled
Nov 12 '18 at 17:02













Sample data is best served as DDL + DML. Please edit your question to include it, your current attempt and your desired results. For more details, read this.

– Zohar Peled
Nov 12 '18 at 17:10





Sample data is best served as DDL + DML. Please edit your question to include it, your current attempt and your desired results. For more details, read this.

– Zohar Peled
Nov 12 '18 at 17:10













Can you have more than one record with null as endDate?

– Zohar Peled
Nov 12 '18 at 19:43





Can you have more than one record with null as endDate?

– Zohar Peled
Nov 12 '18 at 19:43












1 Answer
1






active

oldest

votes


















0














I was able to solve the problem using the following:



Steps:



  • Obtain table of Dates from DateDimension table

  • Join schedules to DateDimension table

  • row_number the schedules to determine which one takes precedence for a given date

  • rank results, order by date

  • dense_rank results, partition by schedule Id, order by date

  • subtract the dense_rank results from the rank results to create a unique Id for each group of contiguous dates

  • Obtain the min and max date for each range of dates

Query to populate test data:



DECLARE @ScheduleTable Table([Index] int not null, StartDate DateTime not null, EndDate DateTime null)
insert into @ScheduleTable ([Index], StartDate, EndDate)
values
(1,'2018-07-13',null)
, (2,'2018-11-14','2018-11-16')
, (3,'2018-11-15','2018-11-15')


Solution:



DECLARE @MinDate Date = dateadd(year,-2,getdate())
DECLARE @MaxDate DateTime = dateadd(year,2,getdate())

select
min(dt) as StartDate
, max(dt) as EndDate
, dense_rank() over(Order by [Index]) [Index]
from
(
select
--Create "groups" using a raw Rank minus dense_rank, partitioned by [Index]
rank() over(order by dt) - dense_rank() over(partition by [Index] order by dt) qlt,
[Index], dt
from
(
select
--Apply row_number to identify which schedule takes precedence on a given day
--Index=2 takes precedence over Index=1
row_number() over(partition by inr.[date] order by ss.[Index] desc) rm,
[date] dt
, ss.*
from
(
--Obtain Table of Dates from DateDimension table
select
[date]
from
[dbo].[DateDimension]dd
where dd.[date] >= @MinDate
and dd.[date] <= @MaxDate
)inr
--join schedules to DateDimension table
left join
(
select *
from
@ScheduleTable
)ss
on ss.StartDate <= inr.[date]
and (ss.enddate >= inr.[date]
or ss.enddate is null)

)inr2
--Exclude any Schedule that is not row_number=1
where inr2.rm = 1
and inr2.[Index] is not null
)inr3
--Group on Index first then Rank minus dense_rank, partitioned by [Index]
group by [Index], qlt
order by StartDate
, [Index]


Results:



StartDate EndDate Index
2018-07-13 2018-11-13 1
2018-11-14 2018-11-14 2
2018-11-15 2018-11-15 3
2018-11-16 2018-11-16 2
2018-11-17 2020-11-12 1





share|improve this answer
























    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53266758%2fconvert-over-lapping-date-ranges-to-rows-of-date-ranges%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    0














    I was able to solve the problem using the following:



    Steps:



    • Obtain table of Dates from DateDimension table

    • Join schedules to DateDimension table

    • row_number the schedules to determine which one takes precedence for a given date

    • rank results, order by date

    • dense_rank results, partition by schedule Id, order by date

    • subtract the dense_rank results from the rank results to create a unique Id for each group of contiguous dates

    • Obtain the min and max date for each range of dates

    Query to populate test data:



    DECLARE @ScheduleTable Table([Index] int not null, StartDate DateTime not null, EndDate DateTime null)
    insert into @ScheduleTable ([Index], StartDate, EndDate)
    values
    (1,'2018-07-13',null)
    , (2,'2018-11-14','2018-11-16')
    , (3,'2018-11-15','2018-11-15')


    Solution:



    DECLARE @MinDate Date = dateadd(year,-2,getdate())
    DECLARE @MaxDate DateTime = dateadd(year,2,getdate())

    select
    min(dt) as StartDate
    , max(dt) as EndDate
    , dense_rank() over(Order by [Index]) [Index]
    from
    (
    select
    --Create "groups" using a raw Rank minus dense_rank, partitioned by [Index]
    rank() over(order by dt) - dense_rank() over(partition by [Index] order by dt) qlt,
    [Index], dt
    from
    (
    select
    --Apply row_number to identify which schedule takes precedence on a given day
    --Index=2 takes precedence over Index=1
    row_number() over(partition by inr.[date] order by ss.[Index] desc) rm,
    [date] dt
    , ss.*
    from
    (
    --Obtain Table of Dates from DateDimension table
    select
    [date]
    from
    [dbo].[DateDimension]dd
    where dd.[date] >= @MinDate
    and dd.[date] <= @MaxDate
    )inr
    --join schedules to DateDimension table
    left join
    (
    select *
    from
    @ScheduleTable
    )ss
    on ss.StartDate <= inr.[date]
    and (ss.enddate >= inr.[date]
    or ss.enddate is null)

    )inr2
    --Exclude any Schedule that is not row_number=1
    where inr2.rm = 1
    and inr2.[Index] is not null
    )inr3
    --Group on Index first then Rank minus dense_rank, partitioned by [Index]
    group by [Index], qlt
    order by StartDate
    , [Index]


    Results:



    StartDate EndDate Index
    2018-07-13 2018-11-13 1
    2018-11-14 2018-11-14 2
    2018-11-15 2018-11-15 3
    2018-11-16 2018-11-16 2
    2018-11-17 2020-11-12 1





    share|improve this answer





























      0














      I was able to solve the problem using the following:



      Steps:



      • Obtain table of Dates from DateDimension table

      • Join schedules to DateDimension table

      • row_number the schedules to determine which one takes precedence for a given date

      • rank results, order by date

      • dense_rank results, partition by schedule Id, order by date

      • subtract the dense_rank results from the rank results to create a unique Id for each group of contiguous dates

      • Obtain the min and max date for each range of dates

      Query to populate test data:



      DECLARE @ScheduleTable Table([Index] int not null, StartDate DateTime not null, EndDate DateTime null)
      insert into @ScheduleTable ([Index], StartDate, EndDate)
      values
      (1,'2018-07-13',null)
      , (2,'2018-11-14','2018-11-16')
      , (3,'2018-11-15','2018-11-15')


      Solution:



      DECLARE @MinDate Date = dateadd(year,-2,getdate())
      DECLARE @MaxDate DateTime = dateadd(year,2,getdate())

      select
      min(dt) as StartDate
      , max(dt) as EndDate
      , dense_rank() over(Order by [Index]) [Index]
      from
      (
      select
      --Create "groups" using a raw Rank minus dense_rank, partitioned by [Index]
      rank() over(order by dt) - dense_rank() over(partition by [Index] order by dt) qlt,
      [Index], dt
      from
      (
      select
      --Apply row_number to identify which schedule takes precedence on a given day
      --Index=2 takes precedence over Index=1
      row_number() over(partition by inr.[date] order by ss.[Index] desc) rm,
      [date] dt
      , ss.*
      from
      (
      --Obtain Table of Dates from DateDimension table
      select
      [date]
      from
      [dbo].[DateDimension]dd
      where dd.[date] >= @MinDate
      and dd.[date] <= @MaxDate
      )inr
      --join schedules to DateDimension table
      left join
      (
      select *
      from
      @ScheduleTable
      )ss
      on ss.StartDate <= inr.[date]
      and (ss.enddate >= inr.[date]
      or ss.enddate is null)

      )inr2
      --Exclude any Schedule that is not row_number=1
      where inr2.rm = 1
      and inr2.[Index] is not null
      )inr3
      --Group on Index first then Rank minus dense_rank, partitioned by [Index]
      group by [Index], qlt
      order by StartDate
      , [Index]


      Results:



      StartDate EndDate Index
      2018-07-13 2018-11-13 1
      2018-11-14 2018-11-14 2
      2018-11-15 2018-11-15 3
      2018-11-16 2018-11-16 2
      2018-11-17 2020-11-12 1





      share|improve this answer



























        0












        0








        0







        I was able to solve the problem using the following:



        Steps:



        • Obtain table of Dates from DateDimension table

        • Join schedules to DateDimension table

        • row_number the schedules to determine which one takes precedence for a given date

        • rank results, order by date

        • dense_rank results, partition by schedule Id, order by date

        • subtract the dense_rank results from the rank results to create a unique Id for each group of contiguous dates

        • Obtain the min and max date for each range of dates

        Query to populate test data:



        DECLARE @ScheduleTable Table([Index] int not null, StartDate DateTime not null, EndDate DateTime null)
        insert into @ScheduleTable ([Index], StartDate, EndDate)
        values
        (1,'2018-07-13',null)
        , (2,'2018-11-14','2018-11-16')
        , (3,'2018-11-15','2018-11-15')


        Solution:



        DECLARE @MinDate Date = dateadd(year,-2,getdate())
        DECLARE @MaxDate DateTime = dateadd(year,2,getdate())

        select
        min(dt) as StartDate
        , max(dt) as EndDate
        , dense_rank() over(Order by [Index]) [Index]
        from
        (
        select
        --Create "groups" using a raw Rank minus dense_rank, partitioned by [Index]
        rank() over(order by dt) - dense_rank() over(partition by [Index] order by dt) qlt,
        [Index], dt
        from
        (
        select
        --Apply row_number to identify which schedule takes precedence on a given day
        --Index=2 takes precedence over Index=1
        row_number() over(partition by inr.[date] order by ss.[Index] desc) rm,
        [date] dt
        , ss.*
        from
        (
        --Obtain Table of Dates from DateDimension table
        select
        [date]
        from
        [dbo].[DateDimension]dd
        where dd.[date] >= @MinDate
        and dd.[date] <= @MaxDate
        )inr
        --join schedules to DateDimension table
        left join
        (
        select *
        from
        @ScheduleTable
        )ss
        on ss.StartDate <= inr.[date]
        and (ss.enddate >= inr.[date]
        or ss.enddate is null)

        )inr2
        --Exclude any Schedule that is not row_number=1
        where inr2.rm = 1
        and inr2.[Index] is not null
        )inr3
        --Group on Index first then Rank minus dense_rank, partitioned by [Index]
        group by [Index], qlt
        order by StartDate
        , [Index]


        Results:



        StartDate EndDate Index
        2018-07-13 2018-11-13 1
        2018-11-14 2018-11-14 2
        2018-11-15 2018-11-15 3
        2018-11-16 2018-11-16 2
        2018-11-17 2020-11-12 1





        share|improve this answer















        I was able to solve the problem using the following:



        Steps:



        • Obtain table of Dates from DateDimension table

        • Join schedules to DateDimension table

        • row_number the schedules to determine which one takes precedence for a given date

        • rank results, order by date

        • dense_rank results, partition by schedule Id, order by date

        • subtract the dense_rank results from the rank results to create a unique Id for each group of contiguous dates

        • Obtain the min and max date for each range of dates

        Query to populate test data:



        DECLARE @ScheduleTable Table([Index] int not null, StartDate DateTime not null, EndDate DateTime null)
        insert into @ScheduleTable ([Index], StartDate, EndDate)
        values
        (1,'2018-07-13',null)
        , (2,'2018-11-14','2018-11-16')
        , (3,'2018-11-15','2018-11-15')


        Solution:



        DECLARE @MinDate Date = dateadd(year,-2,getdate())
        DECLARE @MaxDate DateTime = dateadd(year,2,getdate())

        select
        min(dt) as StartDate
        , max(dt) as EndDate
        , dense_rank() over(Order by [Index]) [Index]
        from
        (
        select
        --Create "groups" using a raw Rank minus dense_rank, partitioned by [Index]
        rank() over(order by dt) - dense_rank() over(partition by [Index] order by dt) qlt,
        [Index], dt
        from
        (
        select
        --Apply row_number to identify which schedule takes precedence on a given day
        --Index=2 takes precedence over Index=1
        row_number() over(partition by inr.[date] order by ss.[Index] desc) rm,
        [date] dt
        , ss.*
        from
        (
        --Obtain Table of Dates from DateDimension table
        select
        [date]
        from
        [dbo].[DateDimension]dd
        where dd.[date] >= @MinDate
        and dd.[date] <= @MaxDate
        )inr
        --join schedules to DateDimension table
        left join
        (
        select *
        from
        @ScheduleTable
        )ss
        on ss.StartDate <= inr.[date]
        and (ss.enddate >= inr.[date]
        or ss.enddate is null)

        )inr2
        --Exclude any Schedule that is not row_number=1
        where inr2.rm = 1
        and inr2.[Index] is not null
        )inr3
        --Group on Index first then Rank minus dense_rank, partitioned by [Index]
        group by [Index], qlt
        order by StartDate
        , [Index]


        Results:



        StartDate EndDate Index
        2018-07-13 2018-11-13 1
        2018-11-14 2018-11-14 2
        2018-11-15 2018-11-15 3
        2018-11-16 2018-11-16 2
        2018-11-17 2020-11-12 1






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 14 '18 at 18:39

























        answered Nov 12 '18 at 21:01









        RIanGillisRIanGillis

        391210




        391210



























            draft saved

            draft discarded
















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53266758%2fconvert-over-lapping-date-ranges-to-rows-of-date-ranges%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Use pre created SQLite database for Android project in kotlin

            Darth Vader #20

            Ondo