Вы можете использовать lead()
и некоторую агрегацию:
select t.*
from (select t.*,
datediff(minute,
ts, lead(ts) over (order by ts)
) as diff_minutes
from (select t.*,
lead(value) over (order by ts) as next_value
from t
) t
where (value < 50 and next_value >= 50) or
(value >= 50 and next_value < 50
) t
where value < 50;
Ваш вопрос немного сложен, потому что вы хотите, чтобы промежуток времени начинался непосредственно перед рассматриваемым периодом. Это на самом деле упрощение. Вышеприведенные реализации:
- Определение значения next .
- Сохранение строки, когда значение next_value или текущее значение превышает пороговое значение или наоборот. Это первая строка до и последняя строка после периода.
- Затем используйте
lead()
, чтобы получить конечную метку времени. - Наконец, отфильтруйте до первой строки.
Другой подход, возможно, проще. Определите группы на основе количества строк, которые ниже порог до или до строки. При этом предыдущая строка сохраняется со следующей группой.
Затем агрегируется:
select min(ts), max(ts),
datediff(minute, min(ts), max(ts)) as diff_minute
from (select t.*,
sum(case when value < 50 then 1 else 0 end) over (order by ts) as grp
from t
) t
group by grp;