You can use analytic functions to group your records into blocks where the speed is 30 or more:
select vid, date_time, speed, status,
case when speed >= 30 then 30 else 0 end as speed_limit,
row_number() over (partition by vid order by date_time)
- row_number() over (
partition by vid, case when speed >= 30 then 30 else 0 end
order by date_time) as chain
from veh_speed;
VID DATE_TIME SPEED STATUS SPEED_LIMIT CHAIN
---------- ------------------- ---------- ------ ----------- ----------
1 15/01/2014 10:00:05 0 N 0 0
1 15/01/2014 10:00:10 10 Y 0 0
1 15/01/2014 10:00:15 30 Y 30 2
1 15/01/2014 10:00:20 35 Y 30 2
1 15/01/2014 10:00:25 45 Y 30 2
1 15/01/2014 10:00:27 10 Y 0 3
1 15/01/2014 10:00:29 0 Y 0 3
1 15/01/2014 10:00:30 20 Y 0 3
1 15/01/2014 10:00:35 32 Y 30 5
1 15/01/2014 10:00:40 33 Y 30 5
1 15/01/2014 10:00:45 35 Y 30 5
1 15/01/2014 10:00:50 38 Y 30 5
1 15/01/2014 10:00:55 10 Y 0 7
I can't take credit for the trick using two row_number()
calls to generate chains of records, unfortunately, I picked that up somewhere (possibly here). The actual value of chain
doesn't matter, just that they are unique within each vid
and the same for all records in a contiguous block of records matching your criteria.
You're only interested in the chains of related records where the 'speed limit' was 30 (and that could just as easily be a Y/N flag or whatever), so you can use that and filter out those where the chain's speed was less than 30; and then use normal aggregate functios to get what you want:
select vid,
min(date_time) as start_date_time,
max(date_time) as end_date_time,
max(speed) as max_speed
from (
select vid, date_time, speed, status,
case when speed >= 30 then 30 else 0 end as speed_limit,
row_number() over (partition by vid order by date_time)
- row_number() over (
partition by vid, case when speed >= 30 then 30 else 0 end
order by date_time) as chain
from veh_speed
)
where speed_limit = 30
group by vid, chain
order by vid, start_date_time;
VID START_DATE_TIME END_DATE_TIME MAX_SPEED
---------- ------------------- ------------------- ----------
1 15/01/2014 10:00:15 15/01/2014 10:00:25 45
1 15/01/2014 10:00:35 15/01/2014 10:00:50 38