Это проблема групп и островов.Для этой версии, я думаю, lag()
и накопленная сумма являются лучшим решением:
select t.*,
sum(case when prev_state = state then 0 else 1 end) over (order by epoch) as state_idx
from (select t.*, lag(state) over (order by epoch) as prev_state
from t
) t;
lag()
получает предыдущее состояние.case
присваивает флагу значение 1 или 0 в зависимости от того, изменилось ли состояние.sum() over
подсчитывает количество таких изменений.