Postgres: агрегировать строки на основе изменения флага - PullRequest
0 голосов
/ 07 мая 2020

Привет, ребята, может, кто-нибудь знает об этом. У меня есть таблица в таком формате:

id          timestamp           status value 
82240589    2020-03-01 09:13:46 70     22.00
82240589    2020-03-01 09:13:57 70     34.00
82240589    2020-03-01 09:14:14 70     21.00
82240589    2020-03-01 09:14:22 70     47.00
82240589    2020-03-01 09:14:33 70     32.00
82240589    2020-03-01 09:14:43 83     37.00
82240589    2020-03-01 09:14:52 83     44.00
82240589    2020-03-01 09:15:01 83     39.00
82240589    2020-03-01 09:15:10 70     40.00
82240589    2020-03-01 09:15:19 70     40.00
82240589    2020-03-01 09:16:30 70      5.00
82240589    2020-03-01 09:16:37 70     43.00
82240589    2020-03-01 09:16:46 70     46.00
82240589    2020-03-01 09:16:53 70     53.00
82240589    2020-03-01 09:17:00 70     55.00
82240589    2020-03-01 09:17:08 70     50.00
82240589    2020-03-01 09:17:16 70     46.00
82240589    2020-03-01 09:17:52 70     10.00

Мне нужно агрегировать вывод на основе идентификатора и изменения статуса. Кроме того, мне нужно вычислить, например, сумму по всем значениям за период. Так, например, результат выглядит так:

id          timestamp_start         timestamp_end               status sum_value
82240589    2020-03-01 09:13:46     2020-03-01 09:14:33         70     ####
82240589    2020-03-01 09:14:43     2020-03-01 09:15:01         83     ####
82240589    2020-03-01 09:15:10     2020-03-01 09:17:52         70     ####

1 Ответ

0 голосов
/ 07 мая 2020

Это проблема .

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

Как мы видим, различные «группы», которые приводят к флагу состояния, теперь имеют уникальный номер, который можно использовать для группировки / агрегирования, который затем выполняется в самом внешнем запросе.

Вложение запросов необходимо, потому что вы не можете вкладывать вызовы оконных функций.

Онлайн-пример

...