SQL 查找前 8 小时内标记的总时数
SQL finding total flagged hours within first 8 hours worked
我的目标是找到一天中每个人的轮班工作总时数或每人轮班的分数,这些小时数被标记为一个值,并且在任何一天的前 8 个小时内工作,不包括休息时间。然后显示标记的班次以及符合条件的总价值。
例子
- 凌晨 2 点 - 凌晨 4 点(2 小时)- 正常班次
- 上午 5 点 - 上午 9 点(4 小时)- 标记班次
- 上午 10 点 - 下午 3 点(5 小时)- 标记班次
符合条件的总计 4 小时(上午 5 点 - 上午 9 点)+ 2 小时(上午 10 点 - 中午 12 点)
来源Table格式
人号 |工作日期 |开始时间 |结束时间 |工作小时数(预先计算)|转换类型
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')
结果集
+----------+------------+---------------------+---------------------+------------------------------+-----------+---------------+
| 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 |
+----------+------------+---------------------+---------------------+------------------------------+-----------+---------------+
以下是我对要求的理解:
- 收集每位用户每天前 8 小时完成的工作
- 如果班次在 8 小时之前开始并在 8 小时之后结束,则应标记用户到达 8 小时之前发生的小时数
- 过滤掉所有未标记的班次
- 过滤掉所有不符合条件的班次
为了解决我使用了两个窗口函数:
- sum(TotalHours) over (...) 以确定当前班次和之前所有班次的工作小时数的累计总和
- (8 - lag(CumulativeWork, 1, 0)) over (...) 以确定进入当前班次还剩多少资格。
代码如下:
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
我的目标是找到一天中每个人的轮班工作总时数或每人轮班的分数,这些小时数被标记为一个值,并且在任何一天的前 8 个小时内工作,不包括休息时间。然后显示标记的班次以及符合条件的总价值。
例子
- 凌晨 2 点 - 凌晨 4 点(2 小时)- 正常班次
- 上午 5 点 - 上午 9 点(4 小时)- 标记班次
- 上午 10 点 - 下午 3 点(5 小时)- 标记班次
符合条件的总计 4 小时(上午 5 点 - 上午 9 点)+ 2 小时(上午 10 点 - 中午 12 点)
来源Table格式
人号 |工作日期 |开始时间 |结束时间 |工作小时数(预先计算)|转换类型
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')
结果集
+----------+------------+---------------------+---------------------+------------------------------+-----------+---------------+
| 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 |
+----------+------------+---------------------+---------------------+------------------------------+-----------+---------------+
以下是我对要求的理解:
- 收集每位用户每天前 8 小时完成的工作
- 如果班次在 8 小时之前开始并在 8 小时之后结束,则应标记用户到达 8 小时之前发生的小时数
- 过滤掉所有未标记的班次
- 过滤掉所有不符合条件的班次
为了解决我使用了两个窗口函数:
- sum(TotalHours) over (...) 以确定当前班次和之前所有班次的工作小时数的累计总和
- (8 - lag(CumulativeWork, 1, 0)) over (...) 以确定进入当前班次还剩多少资格。
代码如下:
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