Checking for time range overlap, the watchman problem [SQL]

后端 未结 4 1695
故里飘歌
故里飘歌 2020-12-09 13:26

I am running into a road block on a larger problem.

As part of a large query I need to solve a \"night watchman\" problem. I have a table with schedule shifts as suc

4条回答
  •  甜味超标
    2020-12-09 13:44

    Here is a way to flatten date range like this

    Start          | End
    2009-1-1 06:00 | 2009-1-1 18:00
    2009-2-1 20:00 | 2009-2-2 04:00
    2009-2-2 06:00 | 2009-2-2 14:00
    

    You have to compare previous and next dates in each row and see whether

    • Current row's Start date falls between previous row's date range.
    • Current row's End date falls between next row's date range.

    alt text

    Using above code, implementing UDF is as simple as followed.

    create function fnThereIsWatchmenBetween(@from datetime, @to datetime)
    returns bit
    as
    begin
        declare @_Result bit
    
        declare @FlattenedDateRange table (
            Start   datetime,
            [End]   datetime
        )
    
        insert  @FlattenedDateRange(Start, [End])
        select  distinct 
                Start = 
                    case 
                        when Pv.Start is null then Curr.Start 
                        when Curr.Start between Pv.Start and Pv.[End] then Pv.Start
                        else Curr.Start 
                    end,
                [End] = 
                    case 
                        when Curr.[End] between Nx.Start and Nx.[End] then Nx.[End] 
                        else Curr.[End] 
                    end
        from    shift Curr
                left join shift Pv on Pv.ID = Curr.ID - 1 --; prev
                left join shift Nx on Nx.ID = Curr.ID + 1 --; next
    
        if exists(  select  1
                    from    FlattenedDateRange R
                    where   @from between R.Start and R.[End]
                            and @to between R.Start and R.[End]) begin
            set @_Result = 1    --; There is/are watchman/men during specified date range
        end
        else begin
            set @_Result = 0    --; There is NO watchman
        end
    
        return @_Result
    end
    

提交回复
热议问题