sql >> データベース >  >> RDS >> Sqlserver

時間間隔の計算方法は?

    いくつかのスケジューリング データを消化するには、この問題を解決する必要がありました。これにより、複数のオンライン時間が許可されますが、重複しないことが前提となります。

    select convert(datetime,'1/1/2015 5:00 AM') StartDateTime,  convert(datetime,'1/1/2015 5:00 PM') EndDateTime, convert(varchar(20),'Online') IntervalType into #CapacityIntervals
    insert into #CapacityIntervals select '1/1/2015 4:00 AM' StartDateTime,  '1/1/2015 6:00 AM' EndDateTime, 'Offline' IntervalType
    insert into #CapacityIntervals select '1/1/2015 5:00 AM' StartDateTime,  '1/1/2015 6:00 AM' EndDateTime, 'Offline' IntervalType
    insert into #CapacityIntervals select '1/1/2015 10:00 AM' StartDateTime,  '1/1/2015 12:00 PM' EndDateTime, 'Offline' IntervalType
    insert into #CapacityIntervals select '1/1/2015 11:00 AM' StartDateTime,  '1/1/2015 1:00 PM' EndDateTime, 'Offline' IntervalType
    insert into #CapacityIntervals select '1/1/2015 4:00 PM' StartDateTime,  '1/1/2015 6:00 PM' EndDateTime, 'Offline' IntervalType
    insert into #CapacityIntervals select '1/1/2015 1:30 PM' StartDateTime,  '1/1/2015 2:00 PM' EndDateTime, 'Offline' IntervalType
    
        --Populate your Offline table
        select 
            ROW_NUMBER() over (Order by StartDateTime, EndDateTime) Rownum,
            StartDateTime, 
            EndDateTime
        into #Offline
        from #CapacityIntervals
        where IntervalType in ('Offline','Cleanout')
        group by StartDateTime, EndDateTime
    
        --Populate your Online table
        select 
            ROW_NUMBER() over (Order by StartDateTime, EndDateTime) Rownum,
            StartDateTime, 
            EndDateTime
        into #Online
        from #CapacityIntervals
        where IntervalType not in ('Offline','Cleanout')
    
    
        --If you have overlapping online intervals... check for those here and consolidate.
    
    
        -------------------------------
        --find overlaping offline times
        -------------------------------
        declare @Finished as tinyint
        set @Finished = 0
    
        while @Finished = 0
        Begin
            update #Offline
            set #Offline.EndDateTime = OverlapEndDates.EndDateTime
            from #Offline
            join
                (
                select #Offline.Rownum,
                    MAX(Overlap.EndDateTime) EndDateTime
                from #Offline
                join #Offline Overlap
                on Overlap.StartDateTime between #Offline.StartDateTime and #Offline.EndDateTime
                    and #Offline.Rownum <= Overlap.Rownum
                group by #Offline.Rownum
                ) OverlapEndDates
            on #Offline.Rownum = OverlapEndDates.Rownum
    
            --Remove Online times completely inside of online times
            delete #Offline
            from #Offline
            join #Offline Overlap
            on #Offline.StartDateTime between Overlap.StartDateTime and Overlap.EndDateTime
                and #Offline.EndDateTime between Overlap.StartDateTime and Overlap.EndDateTime
                and #Offline.Rownum > Overlap.Rownum
    
            --LOOK IF THERE ARE ANY MORE CHAINS LEFT    
            IF NOT EXISTS(
                    select #Offline.Rownum,
                        MAX(Overlap.EndDateTime) EndDateTime
                    from #Offline
                    join #Offline Overlap
                    on  Overlap.StartDateTime between #Offline.StartDateTime and #Offline.EndDateTime
                        and #Offline.Rownum < Overlap.Rownum
                    group by #Offline.Rownum
                    )
                SET @Finished = 1
        END
    
        -------------------------------
        --Modify Online times with offline ranges
        -------------------------------
    
        --delete any Online times completely inside offline range
        delete #Online 
        from #Online
        join #Offline
        on #Online.StartDateTime between #Offline.StartDateTime and #Offline.EndDateTime
            and #Online.EndDateTime between #Offline.StartDateTime and #Offline.EndDateTime
    
        --Find Online Times with offline range at the beginning
        update #Online
        set #Online.StartDateTime = #Offline.EndDateTime
        from #Online
        join #Offline
        on #Online.StartDateTime between #Offline.StartDateTime and #Offline.EndDateTime
            and #Online.EndDateTime >= #Offline.EndDateTime
    
        --Find Online Times with offline range at the end
        update #Online
        set #Online.EndDateTime = #Offline.StartDateTime
        from #Online
        join #Offline
        on #Online.StartDateTime <= #Offline.StartDateTime
            and #Online.EndDateTime between #Offline.StartDateTime and #Offline.EndDateTime
    
        --Find Online Times with offline range punched in the middle
        select #Online.Rownum, 
            #Offline.Rownum OfflineRow,
            #Offline.StartDateTime,
            #Offline.EndDateTime,
            ROW_NUMBER() over (Partition by #Online.Rownum order by #Offline.Rownum Desc) OfflineHoleNumber
        into #OfflineHoles
        from #Online
        join #Offline
        on #Offline.StartDateTime between #Online.StartDateTime and #Online.EndDateTime
            and #Offline.EndDateTime between #Online.StartDateTime and #Online.EndDateTime
    
        declare @HoleNumber as integer
        select @HoleNumber = isnull(MAX(OfflineHoleNumber),0) from #OfflineHoles
    
        --Punch the holes out of the online times
        While @HoleNumber > 0
        Begin
            insert into #Online 
            select
                -1 Rownum,
                #OfflineHoles.EndDateTime StartDateTime,
                #Online.EndDateTime EndDateTime
            from #Online
            join #OfflineHoles
            on #Online.Rownum = #OfflineHoles.Rownum
            where OfflineHoleNumber = @HoleNumber
    
            update #Online
            set #Online.EndDateTime = #OfflineHoles.StartDateTime
            from #Online
            join #OfflineHoles
            on #Online.Rownum = #OfflineHoles.Rownum
            where OfflineHoleNumber = @HoleNumber
    
            set @[email protected]
        end
    
    --Output total hours
    select SUM(datediff(second,StartDateTime, EndDateTime)) / 3600.0 TotalHr
    from #Online
    
    --see how it split up the online intervals
    select * 
    from #Online
    order by StartDateTime, EndDateTime
    


    1. Hibernateアノテーションを使用してJavaの日付をmysqlのDATETIME(デフォルトではそのTIMESTAMP)にマップするにはどうすればよいですか?

    2. (大きい?)数の値に対するMySQLINオペレーターのパフォーマンス

    3. 時間範囲内で5分の間隔にグループ化

    4. SYSUTCDATETIME()SQL Server(T-SQL)の例