Найти первый день в группе, где время выходит за границы полуночи - PullRequest
0 голосов
/ 15 ноября 2018

У меня есть таблица, которая подсчитывает, сколько часов человек проработал.У нас есть ночная команда, которая регистрируется в любое время после 16:00 и выходит до 8:00 на следующее утро.Таблица выглядит следующим образом.

 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

В целях отчетности мы хотим связать только эти отработанные часы с датой первого входа в систему, в этом примере 13 ноября 2018 года. Мой идеальный выводбудет выглядеть следующим образом.

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 

Любые идеи о том, как я могу это сделать?Цени любую помощь

Джесс

Ответы [ 3 ]

0 голосов
/ 15 ноября 2018

Вы можете думать об этом как о пробелах и проблеме островов, где смежные часы представляют остров. Вам нужно найти все острова и найти минимальную дату для каждого острова:

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
0 голосов
/ 15 ноября 2018

Это разновидность «пробелов и островков». Вы можете определить соседние часы, вычитая перечисляемую последовательность. После этого вам просто нужно взять максимум над группой.

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
0 голосов
/ 15 ноября 2018

Я обновлю, когда у меня будет рабочий пример, но попробуйте:

SELECT
MIN(WorkDate) OVER (PARTITION BY UserId ORDER BY WorkHour) [ReportingDate]
FROM <YourTable>
WHERE WorkDate >= CAST(DATEADD(DAY, -1, GETDATE()) AS DATE)
...