Это проблема пробелов и островов .
select id,
min("timestamp") as start_at,
max("timestamp") as end_at,
status,
sum(value)
from (
select id, "timestamp", status, value,
group_flag,
sum(group_flag) over (order by "timestamp") as group_nr
from (
select *,
case
when lag(status,1,status) over (partition by id order by "timestamp") = status then 0
else 1
end as group_flag
from data
order by id, "timestamp"
) t1
) t2
group by group_nr, status, id
order by id, start_at
Таким образом, самый внутренний запрос создает флаг, который переключается с 0 на 1 всякий раз, когда изменяется статус (для того же значения id
).
Для заданных данных результат:
id | timestamp | status | value | group_flag
---------+---------------------+--------+-------+-----------
82240589 | 2020-03-01 09:13:46 | 70 | 22.00 | 0
82240589 | 2020-03-01 09:13:57 | 70 | 34.00 | 0
82240589 | 2020-03-01 09:14:14 | 70 | 21.00 | 0
82240589 | 2020-03-01 09:14:22 | 70 | 47.00 | 0
82240589 | 2020-03-01 09:14:33 | 70 | 32.00 | 0
82240589 | 2020-03-01 09:14:43 | 83 | 37.00 | 1
82240589 | 2020-03-01 09:14:52 | 83 | 44.00 | 0
82240589 | 2020-03-01 09:15:01 | 83 | 39.00 | 0
82240589 | 2020-03-01 09:15:10 | 70 | 40.00 | 1
82240589 | 2020-03-01 09:15:19 | 70 | 40.00 | 0
82240589 | 2020-03-01 09:16:30 | 70 | 5.00 | 0
82240589 | 2020-03-01 09:16:37 | 70 | 43.00 | 0
82240589 | 2020-03-01 09:16:46 | 70 | 46.00 | 0
82240589 | 2020-03-01 09:16:53 | 70 | 53.00 | 0
82240589 | 2020-03-01 09:17:00 | 70 | 55.00 | 0
82240589 | 2020-03-01 09:17:08 | 70 | 50.00 | 0
82240589 | 2020-03-01 09:17:16 | 70 | 46.00 | 0
82240589 | 2020-03-01 09:17:52 | 70 | 10.00 | 0
Следующий уровень затем создает группы на основе этого флага. Для заданных данных результатом этого является:
id | timestamp | status | value | group_nr
---------+---------------------+--------+-------+---------
82240589 | 2020-03-01 09:13:46 | 70 | 22.00 | 0
82240589 | 2020-03-01 09:13:57 | 70 | 34.00 | 0
82240589 | 2020-03-01 09:14:14 | 70 | 21.00 | 0
82240589 | 2020-03-01 09:14:22 | 70 | 47.00 | 0
82240589 | 2020-03-01 09:14:33 | 70 | 32.00 | 0
82240589 | 2020-03-01 09:14:43 | 83 | 37.00 | 1
82240589 | 2020-03-01 09:14:52 | 83 | 44.00 | 1
82240589 | 2020-03-01 09:15:01 | 83 | 39.00 | 1
82240589 | 2020-03-01 09:15:10 | 70 | 40.00 | 2
82240589 | 2020-03-01 09:15:19 | 70 | 40.00 | 2
82240589 | 2020-03-01 09:16:30 | 70 | 5.00 | 2
82240589 | 2020-03-01 09:16:37 | 70 | 43.00 | 2
82240589 | 2020-03-01 09:16:46 | 70 | 46.00 | 2
82240589 | 2020-03-01 09:16:53 | 70 | 53.00 | 2
82240589 | 2020-03-01 09:17:00 | 70 | 55.00 | 2
82240589 | 2020-03-01 09:17:08 | 70 | 50.00 | 2
82240589 | 2020-03-01 09:17:16 | 70 | 46.00 | 2
82240589 | 2020-03-01 09:17:52 | 70 | 10.00 | 2
Как мы видим, различные «группы», которые приводят к флагу состояния, теперь имеют уникальный номер, который можно использовать для группировки / агрегирования, который затем выполняется в самом внешнем запросе.
Вложение запросов необходимо, потому что вы не можете вкладывать вызовы оконных функций.
Онлайн-пример