SQL-запрос для входа / выхода времени - PullRequest
0 голосов
/ 26 сентября 2019

Мне нужно создать отчет при входе и выходе пользователя из времени.Пока мне удается получить только минимальное и максимальное время.Вот пример таблицы:

ID   | Flag_Location (bit) | Time
----------------------------
1001 | 1                   | 8:00
1001 | 1                   | 9:00
1001 | 1                   | 10:00
1001 | 0                   | 11:00
1001 | 0                   | 12:00
1001 | 1                   | 13:00
1001 | 1                   | 14:00

Вывод, который мне нужен для отчета, выглядит следующим образом:

ID   | ENTERTIME | EXITTIME
-------------------------
1001 | 8:00      | 10:00
1001 | 13:00     | 14:00

Пока мне удается получить только 1 строку результата:

ID   | ENTERTIME | EXITTIME
-------------------------
1001 | 8:00      | 14:00

Ответы [ 3 ]

3 голосов
/ 26 сентября 2019

Вы можете использовать оконную функцию для создания специального Grp

Пример

Select ID
      ,TimeIn = min(Time)
      ,TimeOut = max(Time)
 From  (
        Select *
              ,Grp = sum(case when flag_location=0 then 1 else 0 end ) over (partition by id order by time)
         From YourTable
       ) A
 Where Flag_Location=1
 Group By ID,Grp

Возвращает

ID      TimeIn              TimeOut
1001    08:00:00.0000000    10:00:00.0000000
1001    13:00:00.0000000    14:00:00.0000000

Если это помогает с визуализацией , вложенный запрос генерирует следующее:

enter image description here

0 голосов
/ 26 сентября 2019

Попробуйте запрос ниже (пояснения в коде)

declare @tbl table (ID int, Flag_Location bit, Time varchar(5));
insert into @tbl values
(1001,1,'8:00'),
(1001,1,'9:00'),
(1001,1,'10:00'),
(1001,0,'11:00'),
(1001,0,'12:00'),
(1001,1,'13:00'),
(1001,1,'14:00');


select ID,
       cast(max(ts) as varchar(10)), 
       cast(min(ts) as varchar(10))
from (
    select ID, ts, Flag_Location,
           row_number() over (order by ts) -
           row_number() over (partition by Flag_Location order by ts) grp
    from (
        select *,
               -- add 0 at the beginning for correct cast and cast it to timestamp for correct ordering
               cast(right('00000' + time, 5) as timestamp) ts
        from @tbl
    ) a
) a where Flag_Location = 1
group by ID, grp
0 голосов
/ 26 сентября 2019

Вы можете просто объединить, чтобы идентифицировать группу по и сделать группу по, как показано ниже:

;with cte as (select *, bucket = sum(case when flag_location = 0 then 1 when flag_location = 1 and nextflag = 0 then 2  else 0 end) over (partition by id order by [time]),
    [time] as endtime from
    (
        select *,
         lag(flag_location) over(partition by id order by [time]) nextflag
        from #table4
    ) a
)
select id, min([time]), max([time]) from cte
where flag_location = 1
group by id, bucket

Результаты запроса:

+------+------------------+------------------+
|  id  |    Entertime     |     ExitTime     |
+------+------------------+------------------+
| 1001 | 08:00:00.0000000 | 10:00:00.0000000 |
| 1001 | 13:00:00.0000000 | 14:00:00.0000000 |
+------+------------------+------------------+
...