I used the data from Jeremy's answer above, but went about the problem in a completely different way. This uses a recursive CTE, which, it seems to me, requires SQL Server 2005. It accurately reports the results (I believe), and also reports the number of hours recorded during the timeframe and the total number of minutes (maybe more than 120, because the restriction is just is that each offsite period is less than two hours).
declare @TimeSheetEntries table ( ID int identity not null primary key, StaffID int not null, ClockedIn datetime not null, ClockedOut datetime not null ); insert into @TimeSheetEntries ( StaffID, ClockedIn, ClockedOut ) select 4, '2012-01-01 09:00:00', '2012-01-01 12:00:00' union all select 4, '2012-01-01 13:30:00', '2012-01-01 17:30:00' union all select 5, '2012-01-01 09:00:00', '2012-01-01 12:00:00' union all select 5, '2012-01-01 14:09:00', '2012-01-01 17:30:00' union all select 4, '2012-01-01 18:30:00', '2012-01-01 19:30:00'; WITH ClockData AS ( SELECT ID, StaffID, ClockedIn, ClockedOut AS EffectiveClockout, 1 AS NumClockIns, 0 AS MinutesOff FROM @TimeSheetEntries ts WHERE NOT EXISTS (SELECT ID FROM @TimeSheetEntries tsWhere WHERE tsWhere.ClockedOut BETWEEN DATEADD(hour, -2, ts.ClockedIn) AND ts.ClockedIn) UNION ALL SELECT cd.ID, cd.StaffID, cd.ClockedIn, ts.ClockedOut AS EffectiveClockout, cd.NumClockIns + 1 AS NumClockIns, cd.MinutesOff + DateDiff(minute, cd.EffectiveClockout, ts.ClockedIn) AS MinutesOff FROM @TimeSheetEntries ts INNER JOIN ClockData cd ON ts.StaffID = cd.StaffID AND ts.ClockedIn BETWEEN cd.EffectiveClockout AND dateadd(hour, 2, cd.EffectiveClockout) ) SELECT * FROM ClockData cd WHERE NumClockIns = (SELECT MAX(NumClockIns) FROM ClockData WHERE ID = cd.ID)
This returns:
ID StaffID ClockedIn EffectiveClockout NumClockIns MinutesOff 3 5 2012-01-01 09:00:00.000 2012-01-01 12:00:00.000 1 0 4 5 2012-01-01 14:09:00.000 2012-01-01 17:30:00.000 1 0 1 4 2012-01-01 09:00:00.000 2012-01-01 19:30:00.000 3 150
UPDATE
In case this is unclear, MinutesOff is just the โallowanceโ time or the amount of time โeatenโ between ClockedIn and EffectiveClockout shown on the same line. Thus, StaffID 5 canceled 129 minutes between synchronized time periods, but excluding latency, so MinutesOff is 0 for both rows.