SQL query to convert date ranges to per day records

前端 未结 2 961
执念已碎
执念已碎 2020-12-11 11:52

Requirements

  1. I have data table that saves data in date ranges.
  2. Each record is allowed to overlap previous record(s) (record has a CreatedOn da
相关标签:
2条回答
  • 2020-12-11 12:21

    Actually, since you are working with dates, a Calendar table would be more helpful.

    Declare @StartDate date
    Declare @EndDate date
    
    ;With Calendar As
        (
        Select @StartDate As [Date]
        Union All
        Select DateAdd(d,1,[Date])
        From Calendar
        Where [Date] < @EndDate
        )
    Select ...
    From Calendar
        Left Join MyTable
            On Calendar.[Date] Between MyTable.Start And MyTable.End
    Option ( Maxrecursion 0 );
    

    Addition

    Missed the part about the trumping rule in your original post:

    Set DateFormat MDY;
    Declare @StartDate date = '20110101';
    Declare @EndDate date = '20110501';
    
    -- This first CTE is obviously to represent
    -- the source table
    With SampleData As 
        (
        Select 1 As Id
            , Cast('20110101' As date) As RangeFrom
            , Cast('20110331' As date) As RangeTo
            , Cast('07:00' As time) As Starts
            , Cast('15:00' As time) As Ends
            , CURRENT_TIMESTAMP As CreatedOn
        Union All Select 2, '20110401', '20110531', '08:00', '16:00', DateAdd(s,1,CURRENT_TIMESTAMP )
        Union All Select 3, '20110301', '20110430', '06:00', '14:00', DateAdd(s,2,CURRENT_TIMESTAMP )
        )
        , Calendar As
        (
        Select @StartDate As [Date]
        Union All
        Select DateAdd(d,1,[Date])
        From Calendar
        Where [Date] < @EndDate
        )
        , RankedData As
        (
        Select C.[Date]
            , S.Id
            , S.RangeFrom, S.RangeTo, S.Starts, S.Ends
            , Row_Number() Over( Partition By C.[Date] Order By S.CreatedOn Desc ) As Num
        From Calendar As C
            Join SampleData As S
                On C.[Date] Between S.RangeFrom And S.RangeTo
        )
    Select [Date], Id, RangeFrom, RangeTo, Starts, Ends
    From RankedData
    Where Num = 1   
    Option ( Maxrecursion 0 );
    

    In short, I rank all the sample data preferring the newer rows that overlap the same date.

    0 讨论(0)
  • 2020-12-11 12:25

    Why do it all in DB when you can do it better in memory

    This is the solution (I eventually used) that seemed most reasonable in terms of data transferred, speed and resources.

    1. get actual range definitions from DB to mid tier (smaller amount of data)
    2. generate in memory calendar of a certain date range (faster than in DB)
    3. put those DB definitions in (much easier and faster than DB)

    And that's it. I realised that complicating certain things in DB is not not worth it when you have executable in memory code that can do the same manipulation faster and more efficient.

    0 讨论(0)
提交回复
热议问题