Я бы рекомендовал использовать подход Эрика Х. С этим отказом от ответственности это немного противно, но оно предлагает способ сделать то же самое, если у вас нет доступа к таблице чисел по той или иной причине. Я уверен, что это можно улучшить, я просто хотел попробовать это без таблицы чисел:
Declare @Start DateTime, @End DateTime
Select @Start = '04/01/2010 09:30'
, @End = '04/01/2010 17:30'
--Table Creation Stuff
Declare @y Table (ColleagueId Int, DepartmentId Int, DateIn DateTime, DateOut DateTime)
Insert @y
Select 1, 1, '04/01/2010 08:45' , '04/01/2010 11:45'
Union All Select 2 , 1, '04/01/2010 09:00' , '04/01/2010 12:15'
Union All Select 3 , 1, '04/01/2010 10:00' , '04/01/2010 12:00'
Union All Select 4 , 1, '04/01/2010 12:30' , '04/01/2010 17:00'
Union All Select 1 , 1, '04/01/2010 12:45' , '04/01/2010 17:15'
Union All Select 3 , 1, '04/01/2010 13:00' , '04/01/2010 17:25'
---------
Select DateDiff(minute, @Start, @End) -- TotalTime
- Sum(DateDiff(minute,
Case When DateIn < @Start Then @Start Else DateIn End,
Case When DateOut > @End Then @End Else DateOut End)) --StaffedTime
as UnmannedTime
From
(
Select Min(din) DateIn, dout DateOut
From
(
Select Min(y.DateIn) din, Max(y2.DateOut) dout
From @y y
Inner Join @y y2 on y.DateOut >= y2.DateIn
--you probably want to close the other end of these filters, but leave some room
--(to handle the guy who started @ 7:45, etc...)
Where y.DateIn < @End
and y2.DateOut > @Start
Group By y.DateIn
) x
Group By dout
) q
edit добавлены вышеприведенные операторы case для обработки вычисления StaffedTime, когда определенный период начинается до @Start (или заканчивается после @End)