Twój problem wydaje się polegać na tym, że przedział czasu musi być rozłożony w godzinach. Musisz więc zacząć od wszystkich godzin w ciągu dnia. Następnie obliczasz nakładanie się, sumujesz różnice (poniżej w milisekundach) i konwertujesz wszystko z powrotem na czas dla wyjścia.
with const as (
select dateadd(hour, 1, cast(cast(getdate() -1 as date) as datetime)) as midnight
),
allhours as (
select 0 as hour, midnight as timestart, dateadd(hour, 1, midnight) as timeend from const union all
select 1 as hour, dateadd(hour, 1, midnight), dateadd(hour, 2, midnight) from const union all
select 2 as hour, dateadd(hour, 2, midnight), dateadd(hour, 3, midnight) from const union all
. . .
select 23 as hour, dateadd(hour, 23, midnight), dateadd(hour, 24, midnight) from const
)
select ah.hour,
sum(datediff(ms, (case when ah.timestart >= dt.begin then timestart else dt.begin end),
(case when ah.timeend <= dt.end then ah.timeend else dt.end end)
)
) as totalms,
cast(dateadd(ms, sum(datediff(ms, (case when ah.timestart >= dt.begin then timestart else dt.begin end),
(case when ah.timeend <= dt.end then ah.timeend else dt.end end)
)
),
0) as time
) as totalTime
from allhours ah left outer join
DeviceTable dt
on ah.timestart< coalesce(dt.end, getdate()) and
ah.timeend >= dt.begin
group by ah.hour
order by ah.hour
Ponadto, aby to zadziałało, musisz umieścić „początek” i „koniec” w podwójnych cudzysłowach lub nawiasach kwadratowych. Są to słowa zastrzeżone w T-SQL. I musisz wymienić „…”. z dodatkowymi liniami na godziny od 3 do 22.