MSSQL Start and End Time Grouped by 10 Minute, for Elapsed Time
I need to take a start and end time that is already summarized in one row, and break it out into 10 minute window with the total time between.
Example of summary row.
StartDowntime | EndDowntime | ElapsedSecs
=================================================
1/17/2022 8:00 | 1/17/2022 9:05 | 3900
Desired output.
Datetime | ElapsedSeconds
===================================
1/17/2022 8:00 | 600
1/17/2022 8:10 | 600
1/17/2022 8:20 | 600
1/17/2022 8:30 | 600
1/17/2022 8:40 | 600
1/17/2022 8:50 | 600
1/17/2022 9:00 | 300
1/17/2022 9:10 | 0
1/17/2022 9:20 | 0
What I've tried.
;with cte as
(select MIN(StartDowntime) as MinDate
, MAX(StartDowntime) as MaxDate
, convert(varchar(14),StartDowntime, 120) as StartDate
, DATEPART(minute, StartDowntime) /15 as GroupID
, avg(ElapsedSecs) as AvgAmount
from tblOKDryerDowntime
where StartDowntime >= '1/1/2022 7:00' and EndDowntime <= '1/17/2022 8:00'
group by convert(varchar(14),StartDowntime, 120)
, DATEPART(minute, StartDowntime) /15
, Dryer,DowntimeCode)
select dateadd(minute, 15*GroupID, CONVERT(datetime,StartDate+'00'))
as [Start Date]
, AvgAmount as [Average Amount]
from cte
order by [Start Date] desc
This gives me elapsed by start on the closest 15th minute.
But doesn't stop every 15 minutes.
Solution 1:
Discover the magic of a recursive CTE.
;WITH RCTE AS ( SELECT StartDowntime AS DownDatetime , 600 AS ElapsedSeconds , ElapsedSecs AS RemainingSeconds , EndDowntime , 1 AS Lvl FROM tblOKDryerDowntime UNION ALL SELECT DATEADD(second, ElapsedSeconds, DownDatetime) , iif(RemainingSeconds > ElapsedSeconds, 600, RemainingSeconds) , iif(RemainingSeconds > ElapsedSeconds, RemainingSeconds - ElapsedSeconds, 0) , EndDowntime , Lvl + 1 FROM RCTE WHERE DownDatetime < EndDowntime AND RemainingSeconds > 0 ) SELECT DownDatetime, ElapsedSeconds FROM RCTE ORDER BY DownDatetime;
DownDatetime | ElapsedSeconds :---------------------- | -------------: 2022-01-17 08:00:00.000 | 600 2022-01-17 08:10:00.000 | 600 2022-01-17 08:20:00.000 | 600 2022-01-17 08:30:00.000 | 600 2022-01-17 08:40:00.000 | 600 2022-01-17 08:50:00.000 | 600 2022-01-17 09:00:00.000 | 600 2022-01-17 09:10:00.000 | 300
Demo on db<>fiddle here