Reputation: 1
I need to create a report when the user entering and exiting time. So far I only manage to get the min and max time. Here, the example of table:
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
The output that I need for the report is like this :
ID | ENTERTIME | EXITTIME
-------------------------
1001 | 8:00 | 10:00
1001 | 13:00 | 14:00
So far I only manage to get 1 row of result :
ID | ENTERTIME | EXITTIME
-------------------------
1001 | 8:00 | 14:00
Upvotes: 0
Views: 216
Reputation: 37460
Try below query (explanations in code)
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
Upvotes: 0
Reputation: 13969
You can just bucket the to identify group by and do group by as below:
;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
Query results:
+------+------------------+------------------+
| id | Entertime | ExitTime |
+------+------------------+------------------+
| 1001 | 08:00:00.0000000 | 10:00:00.0000000 |
| 1001 | 13:00:00.0000000 | 14:00:00.0000000 |
+------+------------------+------------------+
Upvotes: 0
Reputation: 81990
You can use the window function to create an ad-hoc Grp
Example
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
Returns
ID TimeIn TimeOut
1001 08:00:00.0000000 10:00:00.0000000
1001 13:00:00.0000000 14:00:00.0000000
If it helps with the visualization, the nested query generates the following:
Upvotes: 3