SQL查找前8个小时内已标记的总小时数

问题描述 投票:-1回答:2

我的目标是查找每天的总工作时间,其中每个人的工作班次或工作班次的分数均标有值,并且属于每天工作的前8小时(不包括休息时间)。然后显示标记的班次以及合格的总值。

示例

  • [2am-4am(2 hrs)-Normal shift
  • [5am-9am(4 hrs-标记班次)
  • [10am-3pm(5 hrs)-Tagged shift

合资格的4小时(5am-9am)+ 2小时(10am-12pm)

源表格式

PersonID |工作日期|开始时间| FinishTime |工作小时数(预先计算)| 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')

结果集

+----------+------------+---------------------+---------------------+------------------------------+-----------+---------------+
| 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             |
+----------+------------+---------------------+---------------------+------------------------------+-----------+---------------+
sql sql-server ranking row-number windowing
2个回答
0
投票

这是我对要求的理解:

  • 收集每个用户每天完成的前8个小时的工作
  • 如果轮班在8小时之前开始并在8小时之后结束,则应标出用户到达8小时之前发生的小时数
  • 过滤掉所有未标记的班次
  • 过滤掉所有没有合格时间的班次

解决我使用了两个窗口功能:

  • sum(TotalHours)over(...),以确定当前班次和之前所有班次工作了多少小时的累积总和
  • ((8-lag(CumulativeWork,1,0))在(...)之上,以确定多少资格才进入当前班次。

这里是代码:

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

和小提琴:http://sqlfiddle.com/#!18/7a8dd/12


-2
投票

尝试一下。

SELECT *
    ,CASE WHEN CAST(FinishTime AS TIME) BETWEEN '05:00' AND '09:00' THEN 4
              WHEN CAST(FinishTime AS TIME) BETWEEN '10:00' AND '15:00' THEN 2
         END EligibleHours
FROM Table1
WHERE ShiftType = 'Tagged'

输出:

| PersonID |             WorkDate |            StartTime |           FinishTime | HoursWorked | ShiftType | EligibleHours |
|----------|----------------------|----------------------|----------------------|-------------|-----------|---------------|
|      100 | 2019-11-26T00:00:00Z | 1900-01-01T05:00:00Z | 1900-01-01T09:00:00Z |           4 |    Tagged |             4 |
|      100 | 2019-11-26T00:00:00Z | 1900-01-01T10:00:00Z | 1900-01-01T15:00:00Z |           5 |    Tagged |             2 |

SQL Fiddle link

© www.soinside.com 2019 - 2024. All rights reserved.