PostgreSQL在时间序列中选择布尔状态

时间:2018-07-11 21:18:24

标签: sql postgresql time-series

我遇到了一个特别的问题,我被困住了并寻求帮助...

我有一个时间序列类型的表,当设备打开或关闭时,我在其中存储开关切换值。状态0事件表示设备已关闭,状态1事件表示设备已打开。

time                | state
------------------------------
2018-06-10 12:20:00 | 0
2018-06-10 12:30:00 | 1
2018-06-10 13:10:00 | 0
2018-06-10 16:50:00 | 1
2018-06-10 20:23:00 | 0
2018-06-10 21:10:00 | 1
2018-06-10 21:30:00 | 0

我需要按小时报告使用情况,这意味着生成如下输出:

date                | in_use
-------------------------------
2018-06-10 12:00:00 | 1
2018-06-10 13:00:00 | 1
2018-06-10 14:00:00 | 0
2018-06-10 15:00:00 | 0
2018-06-10 16:00:00 | 1
2018-06-10 17:00:00 | 1
2018-06-10 18:00:00 | 1
2018-06-10 19:00:00 | 1
2018-06-10 20:00:00 | 1
2018-06-10 21:00:00 | 1
2018-06-10 22:00:00 | 0

我不确定如何使用postgres获得这种类型的结果。 你觉得呢?

谢谢!

1 个答案:

答案 0 :(得分:3)

假设您要使用一个小时的状态,其中日志时间是小于该小时的最大时间(此后,您的示例在16:00错误(应为13:10)和21: 00(应为20:23的状态)):

使用generate_series()获取所有时间。首先,在最短时间使用date_trunc(),在结束时也使用date_trunc(),但在最长时间上加上一个小时。

要获取最大时间少于一小时的状态,请使用相关子查询。因为在最初的一个小时内可能没有这种状态,所以子查询可能返回null。在这种情况下,请使用coalesce()将否定值替换为日志中第一个值的取反(按时间排序)。

SELECT "gs"."date",
       coalesce((SELECT "t2"."state"
                        FROM "elbat" "t2"
                        WHERE "t2"."time" < "gs"."date"
                        ORDER BY "t2"."time" DESC
                        LIMIT 1),
                (SELECT NOT "t3"."state"
                        FROM "elbat" "t3"
                        ORDER BY "t3"."time" ASC
                        LIMIT 1)) "in_use"
       FROM (SELECT generate_series(date_trunc('hour', min("t1"."time")),
                                    date_trunc('hour', max("t1"."time"))
                                    + INTERVAL '1 HOUR',
                                    '1 HOUR') "date"
                    FROM "elbat" "t1") "gs";

db<>fiddle