Reputation: 15923
I am trying to work out how to get the times someone is working on various tasks. There are 3 different levels that can mask events occurring at a lower level. Level 2 hides 0 & 1, level 1 hides 0, but is hidden by 2, and level 0 appears only when nothing else is available
While I can get the stop of one event to end at the next level, I don't know how to get it to continue after the previous event has finished. If what I have for each person is a list of times, and an even for each minute, that would also work for what I want to do.
Current code, and example table:
declare @test table ([Type] varchar(10), [Date] date, [start] time, [stop] time, [level] int)
insert into @test
values ('Shift',getdate(),'08:00','12:00',0),
('WorkEvent',getdate(),'08:10','11:00',1),
('Break',getdate(),'10:00','10:10',2)
select *,
case
when lead([start]) over( partition by [Date] order by start,[stop]) is null then [stop] -- no more records, don't alter stop time
when lead([start]) over( partition by [Date] order by start,[stop]) > [stop] then [stop] -- gap in records (for break or other logout), don't alter stop time
else lead([start]) over( partition by [Date] order by start,[stop]) -- use next records start time as stop time to ensure continuity of work period
end as [NewStop]
from @test
desired results:
Type Date start stop level
Shift 2019-03-01 08:00:00.0000000 08:10:00.0000000 0
WorkEvent 2019-03-01 08:10:00.0000000 10:00:00.0000000 1
Break 2019-03-01 10:00:00.0000000 10:10:00.0000000 2
WorkEvent 2019-03-01 10:10:00.0000000 11:00:00.0000000 1
Shift 2019-03-01 11:00:00.0000000 12:00:00.0000000 0
other result which I could work with:
08:00 Shift
08:01 Shift
.
.
.
08:09 Shift
08:10 WorkEvent
.
.
.
09:59 WorkEvent
10:00 Break
etc.
Upvotes: 2
Views: 64
Reputation: 8962
I'm sure this one is not optimal in terms of speed, and I haven't tested it with different dates. But anyway here is a query which seems to work
with valuable_events(dt, timeSt, [level],tp, knd, min_level, seq) as (
select all_events.*, top_level_x.min_level, ROW_NUMBER() over (order by all_events.dt, all_events.timeSt)
from
( select [Date] as dt, [start] as timeSt, [level], type, 'start' as knd
from @test T1
union
select [Date] as dt, [stop] as timeSt, [level], type, 'stop' as knd
from @test T2
)all_events
outer apply (select max([level]) max_level , min([level]) min_level
from @test top_prio
where all_events.dt = top_prio.Date
and all_events.timeSt between top_prio.start and top_prio.stop
) top_level_x
where all_events.level = top_level_x.max_level
)
select iif(evnt.knd='start', evnt.tp, next_evnt.tp) as [Type],
evnt.dt as [Date],
evnt.timeSt as [start],
next_evnt.timeSt as [stop],
iif(evnt.knd='start', evnt.level, next_evnt.level) as [Level]
--, *
from valuable_events evnt
join valuable_events next_evnt on evnt.seq = next_evnt.seq-1
where not (evnt.level = evnt.min_level
and evnt.knd = 'stop'
and next_evnt.knd = 'start')
Upvotes: 1