К сожалению, делать именно то, что вы хотите, в SQL невозможно.Проблема в том, когда есть постепенные изменения, которые превышают 1%.То есть последовательность значений, таких как:
Без разрыва 1%, но общая разница, основанная на первом значении, составляет 1%.Вы не можете легко сказать, где новая группа должна начинаться, не просматривая все предыдущие данные.
Некоторые базы данных поддерживают рекурсивные CTE, которые позволяют логике находиться в базе данных.Redshift не является одним из них.И рекурсивные CTE по сути являются лишь несколько более эффективным вычислением RBAR (строка за агонизирующей строкой).
Тем не менее, я не уверен, что это имеет большое значение в вашей ситуации (ни один из ваших трехпримеры есть такие).Давайте проигнорируем постепенные изменения и найдем периоды, которые изменяются на основе:
- Изменения источника
- Скачок более чем на 1% между смежными записями
Это выполнимо как проблема пропусков и островов, используя lag()
и совокупную сумму:
select min(start_datetime) as start_datetime,
max(end_datetime) as end_datetime,
sensor_id,
avg(sea_level)
from (select t.*,
sum(case when sensor_id <> prev_sensor_id or
sea_level < 0.99 * prev_sea_level or
sea_level > 1.01 * prev_sea_level
then 1 else 0
end) over (order by start_datetime) as grp
from (select t.*,
lag(sensor_id) over (order by start_datetime) as prev_sensor_id,
lag(sea_level) over (order by start_datetime) as prev_sea_level
from t
) t
) t
group by grp, sensor_id;
Самый внутренний подзапрос получает информацию о предыдущем датчике и уровне моря.Это используется, чтобы определить, где начинается группа.Совокупная сумма в среднем подзапросе присваивает идентификатор группы на основе совокупной суммы запусков до каждой записи.
Наконец, внешний запрос агрегирует значение.