我有一张表格,可以计算一个人的工作时间。我们有一个夜间团队,该团队可以在下午4点之后随时登录,并在第二天早上8点之前注销。该表如下所示。
Workdate WorkHour
2018-11-13 20 -- this was the hour they logged on
2018-11-13 21
2018-11-13 22
2018-11-13 23
2018-11-14 0
2018-11-14 1
2018-11-14 2
2018-11-14 3
2018-11-14 4
2018-11-14 5 -- this was the hour they logged off
出于报告的目的,我们仅要将这些工作时间与他们首次登录的日期(在此示例中为2018年11月13日)相关联。我的理想输出如下所示。
Workdate WorkHour ReportingDate
2018-11-13 20 2018-11-13
2018-11-13 21 2018-11-13
2018-11-13 22 2018-11-13
2018-11-13 23 2018-11-13
2018-11-14 0 2018-11-13
2018-11-14 1 2018-11-13
2018-11-14 2 2018-11-13
2018-11-14 3 2018-11-13
2018-11-14 4 2018-11-13
2018-11-14 5 2018-11-13
关于如何执行此操作的任何想法?感谢任何帮助
杰西
答案 0 :(得分:1)
您可以将其视为间隔和孤岛问题,其中连续时间代表孤岛。您需要找到所有岛屿并找到每个岛屿的最短日期:
DECLARE @T TABLE (userid INT, workdate DATE, workhour INT);
INSERT INTO @t VALUES
(1, '2018-11-13', 20),
(1, '2018-11-13', 21),
(1, '2018-11-13', 22),
(1, '2018-11-13', 23),
(1, '2018-11-14', 0),
(1, '2018-11-14', 1),
(1, '2018-11-14', 2),
(1, '2018-11-14', 3),
(1, '2018-11-14', 4),
(1, '2018-11-14', 5),
(1, '2018-11-20', 6);
WITH cte1 AS (
SELECT userid, workdate, workhour
, DATEADD(HOUR, workhour, CAST(workdate AS DATETIME)) AS workdatetime
FROM @t
), cte2 AS (
SELECT userid, workdate, workhour
, CASE WHEN DATEDIFF(HOUR, LAG(workdatetime) OVER (PARTITION BY userid ORDER BY workdate, workhour), workdatetime) = 1 THEN 0 ELSE 1 END AS chg
FROM cte1
), cte3 AS (
SELECT userid, workdate, workhour
, SUM(chg) OVER (PARTITION BY userid ORDER BY workdate, workhour) AS grp
FROM cte2
)
SELECT userid, workdate, workhour, MIN(workdate) OVER (PARTITION BY userid, grp) AS ReportingDate
FROM cte3
ORDER BY userid, workdate, workhour
答案 1 :(得分:0)
当我有一个可行的示例时,我会进行更新,但是请尝试:
SELECT
MIN(WorkDate) OVER (PARTITION BY UserId ORDER BY WorkHour) [ReportingDate]
FROM <YourTable>
WHERE WorkDate >= CAST(DATEADD(DAY, -1, GETDATE()) AS DATE)
答案 2 :(得分:0)
这是“空白和孤岛”的变体。您可以通过减去枚举序列来确定相邻的小时数。之后,您只需要在组中使用最大值即可。
select t.*,
min(workdate) over (partition by datediff(hour, - seqnum, workdatehour) as imputed_workdate
from (select t.*,
dateadd(hour, workhour, workdate) as workdatehour,
row_number() over (order by workdate, workhour) as seqnum
from t
) t