I have a query that I don\'t really know how to begin with. I\'m hoping someone can help me out with it. I will start by explaining the table
I have a device table with
Something like this might get you started.
select SUM(datediff(second, Begin_dt, End_dt)) as seconds_online
,DATEPART(hour, Begin_dt) as [hour]
from table
where device_status in (1,4,5)
group by DATEPART(hour, Begin_dt)
To format the result you may want to follow this question:
SQL - Seconds to Day, Hour, Minute, Second
Your problem seems to be that the time span needs to be broken up in hours. So, you need to start with all hours in the day. Then you calculate the overlap, sum up the differences (below in milliseconds) and convert everything back to a time for the output.
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
Also, to make this work, you need to wrap "begin" and "end" in double quotes or square brackets. These are reserved words in T-SQL. And you need to replace the ". . ." with additional lines for hours from 3 to 22.