在PostgreSQL中使用row_number进行数据透视

问题描述

我在Postgresql中有一个表架构,用于监视某些设备。根据某种条件,设备将进入监视阶段,如果连续第二天保持该状态,则设备将进入操作阶段。它将一直处于行动阶段,直到病情好转为止。

CREATE TABLE public.monitoring_engine
(
    cell_id character varying(1024) COLLATE pg_catalog."default",monitoring_started_at timestamp without time zone,gap character varying(1024) COLLATE pg_catalog."default",status character varying(1024) COLLATE pg_catalog."default"
)
WITH (
    OIDS = FALSE
)
TABLESPACE pg_default;

ALTER TABLE public.monitoring_engine
    OWNER to postgres;

插入声明

INSERT INTO public.monitoring_engine(cell_id,monitoring_started_at,gap,status) VALUES ('Cell_A','2020-09-15',NULL,'Monitor');
INSERT INTO public.monitoring_engine(cell_id,'2020-09-16','1 day','Action');
INSERT INTO public.monitoring_engine(cell_id,'2020-09-17','2020-09-18','2020-09-20','2 days',status) VALUES ('Cell_B','2020-09-21','2020-09-23','2020-09-24','2020-09-25','2020-09-26','Action');

执行上述查询后,表中将提供以下数据。

cell_id         monitoring_started_at       gap     status
Cell_A          9/15/2020 0:00          NULL        Monitor
Cell_A          9/16/2020 0:00          1 day       Action
Cell_A          9/17/2020 0:00          1 day       Action
Cell_A          9/18/2020 0:00          1 day       Action
Cell_A          9/20/2020 0:00          2 days      Monitor
Cell_B          9/15/2020 0:00          NULL        Monitor
Cell_B          9/17/2020 0:00          2 days      Monitor
Cell_B          9/18/2020 0:00          1 day       Action
Cell_B          9/20/2020 0:00          2 days      Monitor
Cell_B          9/21/2020 0:00          1 day       Action
Cell_B          9/23/2020 0:00          2 days      Monitor
Cell_B          9/24/2020 0:00          1 day       Action
Cell_B          9/25/2020 0:00          1 day       Action
Cell_B          9/26/2020 0:00          1 day       Action

必需的输出

cell_id     monitor_date        first_action_date   last_action_date
Cell_A      9/15/2020 0:00      9/16/2020 0:00      9/18/2020 0:00
Cell_A      9/20/2020 0:00      null                null
Cell_B      9/15/2020 0:00      null                null
Cell_B      9/17/2020 0:00      9/18/2020 0:00      9/18/2020 0:00
Cell_B      9/20/2020 0:00      9/21/2020 0:00      9/21/2020 0:00
Cell_B      9/23/2020 0:00      9/24/2020 0:00      9/26/2020 0:00

所需的输出将取决于连续的日期。如果日期连续性中断,则设备将进入监视阶段。

这需要在Postgresql中完成。

解决方法

这是一个空白问题。我认为最简单的方法是计算最新的“监视器”状态的日期,然后使用它对行进行分组。

select 
    cell_id,monitor_date,min(monitoring_started_at) filter(where status = 'Action') first_action_date,max(monitoring_started_at) filter(where status = 'Action') last_action_date
from (
    select me.*,max(monitoring_started_at) 
            filter(where status = 'Monitor') 
            over(partition by cell_id order by monitoring_started_at) 
            as monitor_date
    from monitoring_engine me
) t
group by cell_id,monitor_date
order by cell_id,monitor_date

Demo on DB Fiddle

cell_id | monitor_date        | first_action_date   | last_action_date   
:------ | :------------------ | :------------------ | :------------------
Cell_A  | 2020-09-15 00:00:00 | 2020-09-16 00:00:00 | 2020-09-18 00:00:00
Cell_A  | 2020-09-20 00:00:00 | null                | null               
Cell_B  | 2020-09-15 00:00:00 | null                | null               
Cell_B  | 2020-09-17 00:00:00 | 2020-09-18 00:00:00 | 2020-09-18 00:00:00
Cell_B  | 2020-09-20 00:00:00 | 2020-09-21 00:00:00 | 2020-09-21 00:00:00
Cell_B  | 2020-09-23 00:00:00 | 2020-09-24 00:00:00 | 2020-09-26 00:00:00