Я пытаюсь создать запрос, который подсчитывает количество дней, отработанных для сотрудников. Он должен сбрасываться, когда в течение нескольких дней подряд происходит перерыв, и я не могу заставить его работать. Любые идеи будут с благодарностью!

Это мой запрос. Я пытаюсь использовать функцию row_number, но я не уверен, что это правильно:

WITH CTE AS (
      select distinct TOT.EMPLOYEEID, TOT.DATE
      from TOTALS TOT
      where TOT.EMPLOYEEID IN ('020576','1200823') and
            TOT.TIMEINSECONDS >= 14400 and
            TOT.DATE >= '2019-01-01'
     )
SELECT CTE.*,
       ROW_NUMBER() OVER (PARTITION BY EMPLOYEEID ORDER BY DATE) AS CONSECUTIVEDAYS
FROM CTE
ORDER BY EMPLOYEEID, DATE;

Вот результат:

EMPLOYEEID        DATE        CONSECUTIVEDAYS
020576        2019-01-01 00:00:00.000        1
020576        2019-01-02 00:00:00.000        2
020576        2019-01-03 00:00:00.000        3
020576        2019-01-04 00:00:00.000        4
020576        2019-01-07 00:00:00.000        5 <---- THIS SHOULD BE 1. THE COUNT SHOULD RESET BECAUSE THE DATES ARE NO LONGER CONSECUTIVE.

020576        2019-01-08 00:00:00.000        6
020576        2019-01-09 00:00:00.000        7
020576        2019-01-10 00:00:00.000        8
020576        2019-01-11 00:00:00.000        9
020576        2019-01-14 00:00:00.000        10 <---THIS SHOULD BE 1. THE COUNT SHOULD RESET BECAUSE THE DATES ARE NO LONGER CONSECUTIVE.

020576        2019-01-15 00:00:00.000        11
020576        2019-01-16 00:00:00.000        12
020576        2019-01-17 00:00:00.000        13
020576        2019-01-21 00:00:00.000        14 <---THIS SHOULD BE 1. THE COUNT SHOULD RESET BECAUSE THE DATES ARE NO LONGER CONSECUTIVE.

020576        2019-01-22 00:00:00.000        15
020576        2019-01-23 00:00:00.000        16
020576        2019-01-24 00:00:00.000        17
020576        2019-01-25 00:00:00.000        18
020576        2019-01-28 00:00:00.000        19 <---THIS SHOULD BE 1. THE COUNT SHOULD RESET BECAUSE THE DATES ARE NO LONGER CONSECUTIVE.

020576        2019-01-29 00:00:00.000        20
020576        2019-01-30 00:00:00.000        21
020576        2019-01-31 00:00:00.000        22
1200823        2019-01-01 00:00:00.000        1
1200823        2019-01-02 00:00:00.000        2
1200823        2019-01-03 00:00:00.000        3
1200823        2019-01-04 00:00:00.000        4
1200823        2019-01-07 00:00:00.000        5 <---THIS SHOULD BE 1. THE COUNT SHOULD RESET BECAUSE THE DATES ARE NO LONGER CONSECUTIVE.
1200823        2019-01-08 00:00:00.000        6
1200823        2019-01-09 00:00:00.000        7
1200823        2019-01-10 00:00:00.000        8
1200823        2019-01-11 00:00:00.000        9
1200823        2019-01-14 00:00:00.000        10 <---THIS SHOULD BE 1. THE COUNT SHOULD RESET BECAUSE THE DATES ARE NO LONGER CONSECUTIVE.
1200823        2019-01-15 00:00:00.000        11
1200823        2019-01-16 00:00:00.000        12
1200823        2019-01-18 00:00:00.000        13 <---THIS SHOULD BE 1. THE COUNT SHOULD RESET BECAUSE THE DATES ARE NO LONGER CONSECUTIVE.
1200823        2019-01-21 00:00:00.000        14 <---THIS SHOULD BE 1. THE COUNT SHOULD RESET BECAUSE THE DATES ARE NO LONGER CONSECUTIVE.
1200823        2019-01-22 00:00:00.000        15
1200823        2019-01-23 00:00:00.000        16
1200823        2019-01-24 00:00:00.000        17
1200823        2019-01-25 00:00:00.000        18
1200823        2019-01-28 00:00:00.000        19 <---THIS SHOULD BE 1. THE COUNT SHOULD RESET BECAUSE THE DATES ARE NO LONGER CONSECUTIVE.
1200823        2019-01-29 00:00:00.000        20
1200823        2019-01-30 00:00:00.000        21
1
kimberly 3 Дек 2019 в 05:59
1
Пометьте свой вопрос базой данных, которую вы используете.
 – 
Gordon Linoff
3 Дек 2019 в 06:07

1 ответ

Вы можете идентифицировать группы соседних номеров строк по-разному. Один из методов - использовать LAG() и определить, где начинаются группы. Тогда совокупная сумма определяет группу.

Последний шаг - ROW_NUMBER() для каждой группы, чтобы получить желаемую нумерацию:

WITH CTE AS (
      select distinct TOT.EMPLOYEEID, TOT.DATE
      from TOTALS TOT
      where TOT.EMPLOYEEID IN ('020576','1200823') and
            TOT.TIMEINSECONDS >= 14400 and
            TOT.DATE >= '2019-01-01'
     )
SELECT t.*,
        ROW_NUMBER() OVER PARTITION BY EMPLOYEEID, GRP ORDER BY Date) as seqnum
FROM (SELECT CTE.*,
             SUM(CASE WHEN prev_date < date - interval '1 day' THEN 1 ELSE 0 END) OVER (PARTITION BY EMPLOYEEID ORDER BY DATE) as grp
             ROW_NUMBER() OVER (PARTITION BY EMPLOYEEID ORDER BY DATE) AS CONSECUTIVEDAYS
      FROM (SELECT CTE.*,
                   LAG(DATE) OVER (PARTITION BY EMPLOYEEID ORDER BY DATE) as prev_date
            FROM CTE
           ) t
     ) t
ORDER BY EMPLOYEEID, DATE;

Обратите внимание, что здесь используются общие функции даты. Обработка дат общеизвестно специфична для базы данных. Это должно быть достаточно легко для адаптации к базе данных, которую вы фактически используете.

1
Gordon Linoff 3 Дек 2019 в 06:10
Это отлично сработало после того, как я внес несколько незначительных изменений! Большое спасибо!
 – 
kimberly
5 Дек 2019 в 01:38