I am aiming to find total hours worked in a day for shifts or fractions of shifts per person that are tagged with a value and fall within the first 8 hours of work, excluding breaks, on any day. Then display tagged shifts along with eligible total value.
Example
Eligible Total 4 hrs (5am - 9am) + 2 hrs (10am - 12pm)
Source Table Format
PersonID | WorkDate | StartTime | FinishTime | HoursWorked (pre calculated) | ShiftType
DECLARE @Table TABLE
(
PersonID INT
, WorkDate DATETIME
, StartTime DATETIME
, FinishTime DATETIME
, HoursWorked DECIMAL(4, 2)
, ShiftType VARCHAR(50)
);
INSERT INTO @Table VALUES (100,'2019-11-26','1900-01-01T02:00:00', '1900-01-01T04:00:00',2,'Normal')
INSERT INTO @Table VALUES (100,'2019-11-26','1900-01-01T05:00:00', '1900-01-01T09:00:00',4,'Tagged')
INSERT INTO @Table VALUES (100,'2019-11-26','1900-01-01T10:00:00', '1900-01-01T15:00:00',5,'Tagged')
Result Set
+----------+------------+---------------------+---------------------+------------------------------+-----------+---------------+
| PersonID | WorkDate | StartTime | FinishTime | HoursWorked (pre calculated) | ShiftType | EligibleHours |
+----------+------------+---------------------+---------------------+------------------------------+-----------+---------------+
| 100 | 2019-11-26 | 1900-01-01T05:00:00 | 1900-01-01T09:00:00 | 4 | Tagged | 4 |
+----------+------------+---------------------+---------------------+------------------------------+-----------+---------------+
| 100 | 2019-11-26 | 1900-01-01T10:00:00 | 1900-01-01T15:00:00 | 5 | Tagged | 2 |
+----------+------------+---------------------+---------------------+------------------------------+-----------+---------------+
Here's my understanding of the requirements:
To solve I used two windowing functions:
Here's the code:
select
PersonID,
WorkDate,
StartTime,
FinishTime,
HoursWorked,
ShiftType,
case
when RemainingWork <= HoursWorked then RemainingWork
when RemainingWork > HoursWorked then HoursWorked
else 0 end as EligibleWork
from
(
select
-- Calculate how much eligible work can happen in a given shift by
-- subtracting the amount of work done in previous shifts from 8
8 - lag (CumulativeWork, 1, 0) over (Partition by PersonID, WorkDate order by StartTime) as RemainingWork
, *
from (
select
-- Create a cumulative sum of the hours worked
sum(HoursWorked) over (Partition by PersonID, WorkDate order by StartTime) as CumulativeWork
, *
from ShiftTable
) a
) b
where shiftType = 'Tagged' and remainingWork > 0
And the fiddle: http://sqlfiddle.com/#!18/7a8dd/12