获取停止(第 x 行)和开始(第 x+1 行)之间的时间间隔
Posted
技术标签:
【中文标题】获取停止(第 x 行)和开始(第 x+1 行)之间的时间间隔【英文标题】:Get time interval between stop (row x) and start (row x+1) 【发布时间】:2016-04-16 23:05:05 【问题描述】:我在 PostgreSQL 9.5 中有一个表,每行有两个时间戳,timestampstart
和 timestampstop
。
CREATE TABLE routes(
ID serial PRIMARY KEY,
TIMESTAMPSTART timestamp default NULL,
TIMESTAMPEND timestamp default NULL
);
现在我不想计算开始和停止之间的间隔,而是停止和下一次开始之间的间隔。所以我想要第 x 行的TIMESTAMPSTOP
和第 x+1 行的TIMESTAMPSTART
之间的间隔。顺便说一句,ID
不是按时间顺序排列的!
【问题讨论】:
如果没有“下一个”行会发生什么?如果有重复值怎么办?除了时间戳之外还按ID
排序?
【参考方案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
可能是最快的。
假设timestampstart
是UNIQUE
,否则你需要定义如何打破关系。 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;
【讨论】:
以上是关于获取停止(第 x 行)和开始(第 x+1 行)之间的时间间隔的主要内容,如果未能解决你的问题,请参考以下文章
用Python编写,print("X"),列出1个三角形,第1行1个X居中,第2行2个X居中,第3行5个X居中,列出10行来。