识别紧邻的行组

时间:2014-05-20 19:10:57

标签: sql postgresql window-functions gaps-and-islands

我正在为学校做一个项目,并且在一周内为三个人提供了一个关于gps录音的数据库。我试图根据他们之间的时间将这些录音分组到旅行中。如果录音距离录音前300秒内,它们被视为同一行程的一部分,否则,它们被视为不同行程的一部分。

到目前为止,我已经设法计算了第n行的记录和第n-1行的记录之间的时差,我现在正在尝试创建一个合并记录介绍行程的功能。在另一种编程语言中,这本来就很容易,但在本课程中我们使用的是PostgreSQL,我并不精通它。

为了解决这个问题,我试图创建一个带有变量的函数,该函数在每次两次录制之间的时差大于300秒时增加,并根据变量分配每一行。这是我目前所获得的,虽然目前,该变量一直重置X,因此将所有行分配给trip 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

1 个答案:

答案 0 :(得分:3)

此查询仅使用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 function lag(),用于查看前一行是否超过5分钟。 (只需使用interval进行比较,无需提取秒数)
  • 窗口聚合函数 count() - 这只是带有OVER子句的基本聚合函数。
    表达式step OR NULL仅离开TRUENULL,其中只有TRUE计入正在运行的计数中,从而达到您想要的结果。

SQL Fiddle(以你提供的那个为基础)。