【问题标题】:In postgres, how do I find records within a range, and then a single record outside the range on both sides?在postgres中,如何找到范围内的记录,然后在两边找到范围外的单个记录?
【发布时间】:2017-08-16 21:32:40
【问题描述】:

我在数据库中有一个包含三个字段的表:idvaluetimestamp

给定两个日期,我知道如何在 postgres 中编写一个查询,使用 timestamp 字段,将查找某个范围内的所有记录。麻烦的是,我还想找到范围之前的最近的单个记录,以及范围之后的最近的单个记录。

所以,如果我有这张桌子:

id | value | timestamp
---+-------+---------------------
 1 |     18| Jan, 1 2017, 09:00:000 
 2 |     16| Jan, 1 2017, 09:05:000
 3 |     14| Jan, 1 2017, 09:21:150
 4 |     12| Jan, 1 2017, 10:01:150
 5 |     13| Jan, 1 2017, 10:07:000
 6 |     09| Jan, 1 2017, 10:23:000

我想编写一个包含时间的查询: Jan, 1 2017, 9:10:000 直到 Jan, 1 2017, 10:05:000

并将返回:

id | value | timestamp
---+-------+---------------------
 2 |     16| Jan, 1 2017, 09:05:000
 3 |     14| Jan, 1 2017, 09:21:150
 4 |     12| Jan, 1 2017, 10:01:150
 5 |     13| Jan, 1 2017, 10:07:000

id 2,是最接近范围底部的记录,但仍小于范围底部。 id 5,是最接近范围顶部但仍大于(或等于)范围顶部的记录。

【问题讨论】:

    标签: postgresql datetime range


    【解决方案1】:

    使用三个联合:

    select * from table where timestamp between start_ts and end_ts
    union all
    (select * from table where timestamp < start_ts order by timestamp desc limit 1)
    union all
    (select * from table where timestamp > end_ts order by timestamp limit 1)
    

    所有这些子查询都符合timestamp 列上的索引。

    【讨论】:

      【解决方案2】:

      我建议你使用UNION

       WITH cte as (
            SELECT * 
            FROM YourTable 
            WHERE timestamp BETWEEN @start AND @end
       ), nearStart as (
            SELECT * 
            FROM YourTable 
            WHERE id = (SELECT Max(id)
                        FROM YourTable
                        WHERE id < (SELECT MIN(ID) FROM cte))
       ), nearEnd as (
            SELECT * 
            FROM YourTable 
            WHERE id = (SELECT MIN(id)
                        FROM YourTable
                        WHERE id > (SELECT MAX(ID) FROM cte))
       )
       SELECT * FROM cte
       UNION ALL
       SELECT * FROM nearStart
       UNION ALL
       SELECT * FROM nearEnd
      

      【讨论】:

      • 娟,你的回答太复杂了。它假设 id-s 与时间戳的顺序相同
      • @DanielVidić 那里没有什么复杂的,但abelisto 的答案更简单。如果 id 不是顺序,您可以更改时间戳的 id,但是应该为时间戳添加一个索引
      猜你喜欢
      • 1970-01-01
      • 2018-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多