【问题标题】:Get time interval between stop (row x) and start (row x+1)获取停止(第 x 行)和开始(第 x+1 行)之间的时间间隔
【发布时间】:2016-04-16 23:05:05
【问题描述】:

我在 PostgreSQL 9.5 中有一个表,每行有两个时间戳timestampstarttimestampstop

CREATE TABLE routes(
    ID serial PRIMARY KEY,
    TIMESTAMPSTART timestamp default NULL,
    TIMESTAMPEND timestamp default NULL
);

现在我不想计算开始和停止之间的间隔,而是停止和下一次开始之间的间隔。所以我想要第 x 行的TIMESTAMPSTOP 和第 x+1 行的TIMESTAMPSTART 之间的间隔。顺便说一句,ID 不是按时间顺序排列的!

【问题讨论】:

  • 如果没有“下一个”行会发生什么?如果有重复值怎么办?除了时间戳之外还按ID 排序?

标签: sql postgresql intervals postgresql-9.5 sql-timestamp


【解决方案1】:

如果“事件”之间没有重叠,那么你可以做一个简单的窗口函数。查询可以很简单:

SELECT id, lead(timestampstart) OVER (ORDER BY timestampstart) -
           timestampend AS timetonext
FROM routes;

SQLFiddle

这个解决方案比Erwin's solution快一个数量级:http://www.sqlfiddle.com/#!15/551e2/4

【讨论】:

  • 是的,如果有一个exclusion constraint,这个查询将是等效的,并且更简单、更快。一个极端情况的区别:我的查询假设timestampstart > r.timestampend,而这也允许相等:timestampstart >= r.timestampend。范围类型(​​或 SQL OVERLAPS 运算符)默认将上限视为独占,下一个间隔可以以与上一个结束相同的时间戳开始,并且不被视为重叠。
【解决方案2】:

不能只使用简单的window function lead() or lag(),因为您想要两个不同列之间的间隔。

可以使用添加谓词的各种连接变体。有一个索引 timestampstart LATERAL join 和 LIMIT 1 可能是最快的。

假设timestampstartUNIQUE,否则你需要定义如何打破关系。 UNIQUE 约束还可以提供性能所需的索引:

SELECT r.*, r1.timestampstart - r.timestampend AS interval_til_start_of_next_row
FROM   routes r
LEFT   JOIN LATERAL (
   SELECT timestampstart
   FROM   routes
   WHERE  timestampstart > r.timestampend
   ORDER  BY timestampstart  -- or BY timestampstart, id - to break ties if not unique
   LIMIT  1
   ) r1 ON true;

【讨论】:

    猜你喜欢
    • 2023-03-10
    • 1970-01-01
    • 2021-05-14
    • 2021-09-11
    • 2017-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多