识别非常接近的行组
Posted
技术标签:
【中文标题】识别非常接近的行组【英文标题】:Identify groups of rows in close proximity 【发布时间】:2014-05-20 19:10:56 【问题描述】:我正在为学校做一个项目,并在一周的课程中获得了一个关于三个人的 GPS 记录的数据库。我正在尝试根据它们之间的时间将这些录音分组为旅行。如果一段录音距离之前的录音在 300 秒内,则将它们视为同一行程的一部分,否则,将它们视为不同行程的一部分。
到目前为止,我已经设法计算出第 n 行的记录与第 n-1 行的记录之间的时间差,我现在正在尝试创建一个用于合并记录介绍行程的函数。这在另一种编程语言中会很容易,但在本课程中,我们使用的是我不太熟悉的 PostgreSQL。
为了解决这个问题,我正在尝试创建一个带有变量的函数,每次两个记录之间的时间差大于 300 秒时该变量都会增加,并根据该变量将每一行分配给一次行程。这是我目前所得到的,尽管目前,变量一直重置 X,因此将所有行分配给行程 1...
CREATE OR REPLACE FUNCTION tripmerge(time_diff double precision)
RETURNs integer AS $$
declare
X integer := 1;
ID integer;
BEGIN
IF time_diff < 300 THEN
ID = X;
ELSE
ID =X;
X:=X+1;
END IF;
RETURN ID;
END;$$
LANGUAGE plpgsql;
如何更改X
不会一直重置?我正在使用 PostgreSQL 9.1。
编辑:
这是我正在使用的表格:
curr_rec (timestamp), prev_rec (timestamp), time_diff (double precision)
这是数据集的一个样本:
'2013-11-14 05:22:33.991+01',null ,null
'2013-11-14 09:15:40.485+01','2013-11-14 05:22:33.991+01',13986.494
'2013-11-14 09:17:04.837+01','2013-11-14 09:15:40.485+01',84.352
'2013-11-14 09:17:43.055+01','2013-11-14 09:17:04.837+01',38.218
'2013-11-14 09:23:24.205+01','2013-11-14 09:17:43.055+01',341.15
预期结果会增加一列:
tripID
1
2
2
2
3
我认为这个小提琴应该可以工作:http://sqlfiddle.com/#!1/4e3e5/1/0
【问题讨论】:
triplegs
?三胞胎?我已将问题阅读了两次,但仍然不知道您要达到什么目的。请添加:您的 Postgres 版本、表定义(psql 中的\d recordings
)、示例数据和结果数据示例——或者更好的是fiddle。
我明白你的意思并编辑了文本以试图澄清我的问题,谢谢:)
可能可以通过单个查询来解决,like this one. 但我仍然没有看到表定义或示例数据或预期结果...
作为一般说明,听起来您正在尝试在关系数据库中为您的问题实施程序解决方案。在关系数据库中使用过程解决方案通常不是一个好主意。重新考虑你的问题。 SQL 是一种声明性 语言;看看你能不能想出一种用 SQL 表达你需要的方法。我还要注意,我的经验是你很少需要在 PostgreSQL 中使用过程代码。它的特性使得在比其他数据库更广泛的问题中找到声明式(纯 SQL)解决方案成为可能 *coughOraclecough*。
Erwin:我添加了所有需要的数据以及我希望从中得到的数据以及小提琴。如果它可以通过一个很好的查询来解决,尽管你链接到的那个对我来说远远超出了我能够解释的程度。
【参考方案1】:
此查询仅使用 curr_rec
,而不使用其他冗余的预计算列:
SELECT 1 + count(step OR NULL) OVER (ORDER BY curr_rec) AS trip_id
FROM (
SELECT curr_rec
,lag(curr_rec) OVER (ORDER BY curr_rec) AS prev_rec
,curr_rec - lag(curr_rec) OVER (ORDER BY curr_rec)
> interval '5 min' AS step
FROM timestamps
) x;
主要特点是:
window functionlag()
,用于查看上一行是否超过 5 分钟前。 (只需使用interval
进行比较,无需提取秒数)
窗口聚合函数count()
- 这只是带有OVER
子句的基本聚合函数。
表达式step OR NULL
只留下TRUE
或NULL
,其中只有TRUE
被计入运行计数,从而达到您想要的结果。
SQL Fiddle(在您提供的基础上构建)。
【讨论】:
以上是关于识别非常接近的行组的主要内容,如果未能解决你的问题,请参考以下文章