Det enklaste sättet att närma sig detta är att använda variabler och jag tror att det enklaste sättet är att lägga till två variabler, en antalet "upp" och den andra antalet "ner" upp till en given rad. En given sekvens av ups har ett konstant värde för antalet föregående "downs" och vice versa. Denna logik kan användas för aggregering.
Den resulterande frågan är:
select result, min(time_stamp) as start_time, max(time_stamp) as end_time
from (select r.*,
(@ups := @ups + (result = 'up')) as ups,
(@downs := @downs + (result = 'down')) as downs
from results r cross join
(select @ups := 0, @downs := 0) vars
where service_id = 1
order by time_stamp
) r
group by result, (case when result = 'up' then downs else ups end);