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

У меня есть следующий набор результатов, который я получаю с SQL Сервера:

employeeNumber | start_date | start_time | end_date     | end_time
---------------+------------+------------+--------------+----------
123            | 10-03-2020 |  18:13:55  |  10-03-2020  | 22:59:46
123            | 10-03-2020 |  18:24:22  |  10-03-2020  | 22:59:51
123            | 10-03-2020 |  23:24:22  |  10-03-2020  | 23:59:51
123            | 11-03-2020 |  18:25:25  |  11-03-2020  | 20:59:51
123            | 12-03-2020 |  18:40:22  |  12-03-2020  | 22:59:52

В некоторых случаях у меня есть несколько строк для одного и того же времени перекрытия (строки 1 и 2), как указано выше, но с разное время начала и окончания (разница в секундах или минутах).

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

employeeNumber | start_date | start_time | end_date     | end_time    
---------------+------------+------------+--------------+----------
123            | 10-03-2020 |  18:13:55  |  10-03-2020  | 22:59:46
123            | 10-03-2020 |  23:24:22  |  10-03-2020  | 23:59:51
123            | 11-03-2020 |  18:25:25  |  11-03-2020  | 20:59:51
123            | 12-03-2020 |  18:40:22  |  12-03-2020  | 22:59:52

Ниже мой запрос:

select 
    employeeNumber, start_date, start_time, end_date, end_time
from 
    emp_data
where 
    employeeNumber = 123
order by 
    employeeNumber;

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

Любая помощь приветствуется, поскольку я не очень хорошо знаком с SQL Server.

1 Ответ

1 голос
/ 21 марта 2020

Это сложно. Вы должны отслеживать «начинается» и «заканчивается». Я собираюсь предположить, что ваши столбцы datetime s или что-то подобное, которые могут быть объединены в один столбец:

with e as (
      select e.employeeNumber, v.dt, sum(v.inc) as inc,
             sum(sum(v.inc)) over (partition by e.employeeNumber order by v.dt) as in_outs
      from emp_data e cross apply
           (values (start_date + start_time, 1),
                   (end_date + end_time, -1)
           ) v(dt, inc)
      group by e.employeeNumber, v.dt
     )
select employeeNumber, min(dt) as start_datetime, max(dt) as end_datetime
from (select e.*,
             sum(case when in_outs = 0 then 1 else 0 end) over (partition by employeeNumber order by dt) as grp
      from e
     ) e
where in_outs <> 0
group by employeeNumber, grp;

Здесь - это скрипта db <>.

Что это делает?

  • Сначала дата / время преобразуются в время даты.
  • Затем столбцы не поворачиваются и идентифицируются как начало и конец вместе с + 1 или -1, чтобы указать, является ли сотрудник «входящим» или «существующим» в то время.
  • Они накапливаются.
  • Теперь у вас есть проблема с пробелами и островками, где вы хотите найти продолжение периодов "в" с. «Острова» идентифицируются с помощью накопленной суммы «ins».
  • Затем они агрегируются.

РЕДАКТИРОВАТЬ:

Вы можете заменить накопленную сумму на :

from (select e.*,
             (select sum(case when e2.in_outs = 0 then 1 else 0 end) 
              from e e2
              where e2.employeeNumber = e.employeeNumber
                    e2.dt <= e.dt
             ) as grp
      from e
     ) e
...