value:------------------

问题描述 投票:1回答:1

我需要能够过滤一个数据集,每3小时只显示第一个实例。如果发现了一个实例,那么之后3小时内发生的任何其他实例都应该被隐藏。

我所能找到的最接近的方法是使用 date_trunc 来获取每个小时的第一个实例,但我需要具体隐藏到第一个实例后的3个小时。

示例数据。

+------------------------+-------+
|       Timestamp        | Value |
+------------------------+-------+
| "2015-12-29 13:35:00"  |    65 |
| "2015-12-29 13:40:00"  |    26 |
| "2015-12-29 13:45:00"  |    80 |
| "2015-12-29 13:50:00"  |    10 |
| "2015-12-29 16:40:00"  |    76 |
| "2015-12-29 16:45:00"  |    73 |
| "2016-01-04 08:05:00"  |    87 |
| "2016-01-04 08:10:00"  |    90 |
| "2016-01-04 08:15:00"  |    52 |
| "2016-01-04 08:20:00"  |    90 |
| "2016-01-04 08:25:00"  |    23 |
| "2016-01-04 08:30:00"  |    96 |
| "2016-01-04 13:35:00"  |    53 |
| "2016-01-04 13:40:00"  |    15 |
| "2016-01-04 13:45:00"  |    85 |
+------------------------+-------+

预期结果:

+------------------------+-------+
|       Timestamp        | Value |
+------------------------+-------+
| "2015-12-29 13:35:00"  |    65 |
| "2015-12-29 16:40:00"  |    76 |
| "2016-01-04 08:05:00"  |    87 |
| "2016-01-04 13:30:00"  |     7 |
+------------------------+-------+

Anyone have any ideas? Thank you so much for your help.
sql postgresql date select recursive-query
1个回答
0
投票

这是一个棘手的问题,因为你需要跟踪最后一个被选中的记录,以确定下一个记录--所以你不能只用 group by 间隔3小时。

这里有一个使用递归cte的方法。

with recursive cte(ts, value) as (
    select ts, value
    from mytable
    where ts = (select min(ts) from mytable)
    union all
    select x.*
    from (select ts from cte order by ts desc limit 1) c
    cross join lateral (
        select t.ts, t.value
        from mytable t
        where t.ts >= c.ts + interval '3' hour
        order by t.ts
        limit 1
    ) x
)
select * from cte order by ts   

我们的想法是从表中最早的记录开始,然后选择至少3小时后的第一条可用记录进行迭代(假设时间戳列中没有重复的记录)。

需要注意的是 timestamp 并不是一个好的列名选择,因为它与语言关键字(那是一个数据类型)冲突。我把它改成了 ts 中的查询。

DB Fiddle的演示:

ts                  
© www.soinside.com 2019 - 2024. All rights reserved.