微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Postgres:如何在时间段中检查多个值的记录

如何解决Postgres:如何在时间段中检查多个值的记录

我有一个具有以下形状的POSTGRES表:

sensor_id |         recorded_at
----------+--------------------
        A | 2020-01-01 00:00:00
        A | 2020-01-01 00:03:00
        B | 2020-01-01 01:00:00
        C | 2020-01-01 01:03:00
      ... |                 ...

给出一个

  • 开始时间
  • 结束时间
  • 桶宽
  • 传感器ID列表

我想编写一个查询,将范围[start_time,end_time]切成宽度bucket_width的子间隔(存储桶),并针对每个存储桶检查列表中的每个传感器是否具有在该存储桶中包含recorded_at的记录。

例如,假设输入

  • 开始时间= '2020-01-01 00:00:00'
  • 结束时间= '2020-01-01 02:00:00'
  • 桶宽= '1 hour'
  • 传感器ID列表= ['A','B','C']

查询应返回类似

内容
                  t1 |                  t2 | A_count | B_count | C_count
---------------------+---------------------+---------+---------+--------
 2020-01-01 00:00:00 | 2020-01-01 01:00:00 |       2 |       0 |       0
 2020-01-01 01:00:00 | 2020-01-01 02:00:00 |       0 |       1 |       1

我不需要实际计数,因此我想LIMIT 1会出现在某个地方。我只是在示例中包含了它,以帮助弄清楚我在寻找什么。

解决方法

一个选项使用generate_series()来生成行,然后使用left join来生成表,最后使用条件聚合来按传感器获取计数:

select s.ts ts1,s.ts + interval '1 hour' ts2,count(*) filter (where sensor_id = 'A') a_count,count(*) filter (where sensor_id = 'B') b_count,count(*) filter (where sensor_id = 'C') c_count
from generate_series('2020-01-01 00:00:00'::timestamp,'2020-01-01 02:00:00'::timestamp,'1 hour') s(ts)
left join mytable t on t.recorded_at >= s.ts and t.recorded_at < s.ts + interval '1 hour'
group by s.ts

请注意,这会产生一条额外的记录(来自02:00:00 to 03:00:00 ') as compared to your desired results. If you want to avoid that,you can slightly modify the generate_series()`参数,例如:

...
    from generate_series(
        '2020-01-01 00:00:00'::timestamp,'2020-01-01 02:00:00'::timestamp - interval '1 second','1 hour'
     ) s(ts)
...

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。