Получение отдельных строк для перекрывающихся отметок времени - Sql Server - PullRequest
0 голосов
/ 26 марта 2020

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

employeeNumber |    start_time           |  end_time
john           |   10/02/2020 16.30.000  |  11/02/2020 02.00.000
john           |   10/02/2020 20.00.000  |  10/02/2020 22.00.000
john           |   10/02/2020 23.00.000  |  11/02/2020 01.00.000
rick           |   10/02/2020 10.00.000  |  10/02/2020 11.00.000
rick           |   10/02/2020 13.00.000  |  10/02/2020 14.30.000
tom            |   10/02/2020 09:00.000  |  10/02/2020 18.00.000

Как вы можете видеть Джон имеет 3 перекрывающихся записей, Рик имеет 2 непересекающихся записей и Том имеет только 1 запись.

Следовательно, я бы хотел, чтобы результат выглядел следующим образом:

john   |   10/02/2020 16.30.000  |  11/02/2020 02.00.000
rick   |   10/02/2020 10.00.000  |  10/02/2020 11.00.000
rick   |   10/02/2020 13.00.000  |  10/02/2020 14.30.000
tom    |   10/02/2020 09:00.000  |  10/02/2020 18.00.000

Так что с некоторыми исследованиями и большой помощью @Gordon Linoff, следующее sql помогло мне приблизиться к моему результат.

with e as (
select t1.*,s.final_inc from
(
  select e.employeeNumber, v.dt, sum(v.inc) as inc
      from emp_data e cross apply
           (values (start_time, 1),
                   (end_time, -1)
           ) v(dt, inc)
      group by e.employeeNumber, v.dt) t1 

   outer apply

   ( select sum(t2.inc) as final_inc from 

   (select e.employeeNumber,v.dt,sum(v.inc) as inc
      from emp_data e cross apply 
      (values (start_time, 1),
                   (end_time, -1)
           ) v(dt, inc)
           group by e.employeeNumber, v.dt ) t2 
     where t2.employeeNumber = t1.employeeNumber and
           t2.dt<=t1.dt)s
     )

select employeeNumber, min(dt) as start_datetime, max(dt) as end_datetime
from (select e.*,
             (select sum(case when e2.final_inc = 0 then 1 else 0 end) 
              from e e2
              where e2.employeeNumber = e.employeeNumber and
                    e2.dt <= e.dt
             ) as grp
      from e
     ) e
where final_inc <> 0
group by employeeNumber, grp;

Вот БД скрипка с запросом, который я использовал для получения результатов до сих пор. В скрипте второй запрос соответствует предложению @Gordon, однако, поскольку уровень совместимости, установленный для моего SQL сервера, равен 100, он не поддерживает использование порядка на вдоль стороны сумма () более . Следовательно, я использовал external apply для того же самого в моем следующем запросе.

Приведенный выше запрос теперь дает мне следующий вывод:

john   |   10/02/2020 16.30.000  |  11/02/2020 01.00.000
rick   |   10/02/2020 10.00.000  |  10/02/2020 10.00.000
tom    |   10/02/2020 09.00.000  |  10/02/2020 09.00.000
rick   |   10/02/2020 13:00.000  |  10/02/2020 13.00.000

Итак, здесь я столкнулся с 2 проблемами.

  1. Для 2 строк против rick и 1 против tom результат дает только start_time в столбцах start_time и end_time.
  2. Для Джона, хотя он выбрал только одну запись со временем начала как 10/02/2020 16.30.000, что является правильным, но время окончания, которое он взял, составляет 11/02/2020 01.00.000. Однако следует выбрать 11/02/2020 02.00.000.

Любая помощь приветствуется.

...