これは非常に複雑かもしれませんが、機能します。いくつかのCTEを使用して、有用な中間表現を構築します。
declare @Times table (
ID int not null,
StartTime datetime not null,
EndTime datetime not null
)
insert into @Times (ID,StartTime,EndTime)
select 1,'2012-07-04T05:00:00.000','2012-07-04T23:00:00.000' union all
select 2,'2012-07-04T18:00:00.000','2012-07-05T05:00:00.000'
;With Start as (
select MIN(DATEADD(day,DATEDIFF(day,0,StartTime),0)) as StartDay from @Times
), Ends as (
select MAX(EndTime) EndTime from @Times
), Nights as (
select DATEADD(hour,-2,StartDay) as NightStart,DATEADD(hour,6,StartDay) as NightEnd from Start
union all
select DATEADD(DAY,1,NightStart),DATEADD(DAY,1,NightEnd) from Nights n
inner join Ends e on n.NightStart < e.EndTime
), Overlaps as (
select
t.ID,
CASE WHEN n.NightStart > t.StartTime THEN n.NightStart ELSE t.StartTime END as StartPeriod,
CASE WHEN n.NightEnd < t.EndTime THEN n.NightEnd ELSE t.EndTime END as EndPeriod
from
@Times t
inner join
Nights n
on
t.EndTime > n.NightStart and
t.StartTime < n.NightEnd
), Totals as (
select ID,SUM(DATEDIFF(hour,StartPeriod,EndPeriod)) as TotalHours
from Overlaps
group by ID
)
select
*
from
@Times t
inner join
Totals tot
on
t.ID = tot.ID
結果:
ID StartTime EndTime ID TotalHours
----------- ----------------------- ----------------------- ----------- -----------
1 2012-07-04 05:00:00.000 2012-07-04 23:00:00.000 1 2
2 2012-07-04 18:00:00.000 2012-07-05 05:00:00.000 2 7
ID
相関関係を機能させるには、列を追加する必要があることに注意してください。
Start
CTEは、該当する最も早い深夜を見つけます。End
CTEは、重複する夜を見つける必要がある最後の時間を見つけます。次に、再帰Nights
CTEは、これら2つの時点の間で毎晩計算します。次に、これを元のテーブル(in Overlaps
)に結合して、各夜に適用される期間を見つけます。最後に、ではTotals
、重複する各期間が何時間寄与したかを計算します。
これは、複数日のイベントで機能するはずです。Totals
部分時間をカウントする必要がある場合は、分を使用するようにCTEを変更するか、他の丸め関数を適用することをお勧めします。