Это также можно сделать с помощью рекурсивного CTE
Пример фрагмента:
declare @Table table (
RunID int identity(1,1) primary key,
StartTimeBakery datetime,
EndTimeBakery datetime,
Pallets int
);
insert into @Table (StartTimeBakery, EndTimeBakery, Pallets) values
(DATEADD(day,DATEDIFF(day,-1, GETDATE()),'03:00'), DATEADD(day,DATEDIFF(day,-1, GETDATE()),'21:41'), 135)
,(DATEADD(day,DATEDIFF(day,-1, GETDATE()),'22:00'), DATEADD(day,DATEDIFF(day,-2, GETDATE()),'22:13'), 300)
,(DATEADD(day,DATEDIFF(day,-2, GETDATE()),'23:59'), DATEADD(day,DATEDIFF(day,-4, GETDATE()),'05:23'), 315)
;
with RCTE as
(
select
RunID,
StartTimeBakery as BaseStartTime, EndTimeBakery as BaseEndTime, Pallets as BasePallets,
0 as Lvl,
StartTimeBakery as StartTime,
case
when cast(StartTimeBakery as date) = cast(EndTimeBakery as date)
then EndTimeBakery
else CONVERT(DATETIME,DATEADD(MILLISECOND, -10, DATEADD(DAY, 1, CONVERT(DATETIME2,CONVERT(DATE, StartTimeBakery)))))
end as EndTime,
Pallets
from @Table
where EndTimeBakery > GETDATE()
union all
select RunID, BaseStartTime, BaseEndTime, BasePallets,
Lvl+1,
CONVERT(DATETIME, DATEADD(DAY, 1, CONVERT(DATE,EndTime))),
case when DATEADD(DAY, 1, EndTime) < BaseEndTime then DATEADD(DAY, 1, EndTime) else BaseEndTime end,
Pallets
from RCTE
where EndTime < BaseEndTime
)
select
StartTime AS StartTimeBakery,
EndTime AS EndTimeBakery,
CAST(Pallets * (CAST(DATEDIFF(second, StartTime, EndTime) AS FLOAT) / DATEDIFF(second, BaseStartTime, BaseEndTime)) AS DECIMAL(10,2)) as PercDiffMinutes
from RCTE
order by BaseStartTime, StartTime;