如何用postgres找到成对的事件?

时间:2018-06-01 10:43:27

标签: psql

我有一个事件表:

             ts             |  user  | reason 
----------------------------+--------+--------
 2018-06-01 10:44:15.52+01  | 359999 | START
 2018-06-01 10:44:29.521+01 | 359999 | STOP
 2018-06-01 10:44:43.52+01  | 359998 | START
 2018-06-01 10:44:55.52+01  | 359999 | START
 2018-06-01 10:44:59.521+01 | 359998 | STOP
 2018-06-01 10:45:07.52+01  | 359999 | STOP
 2018-06-01 10:46:16.52+01  | 359999 | START

我想找到一对事件:

  user  |           start            |            stop            
--------+----------------------------+----------------------------
 359999 | 2018-06-01 10:44:15.52+01  | 2018-06-01 10:44:29.521+01
 359998 | 2018-06-01 10:44:43.52+01  | 2018-06-01 10:44:59.521+01
 359999 | 2018-06-01 10:44:55.52+01  | 2018-06-01 10:45:07.52+01
 359999 | 2018-06-01 10:46:16.52+01  |

什么样的查询可以做到这一点?

2 个答案:

答案 0 :(得分:1)

您可以使用window function轻松完成此操作。除此之外,这些允许您引用查询结果中的下一行/上一行(通过lead()lag())。例如:

SELECT "user", ts AS start, next_ts AS stop
FROM (
  SELECT *, lead(ts) OVER (PARTITION BY "user" ORDER BY ts) AS next_ts
  FROM events
  WHERE reason IN ('START', 'STOP')
) AS ts_pairs
WHERE reason = 'START'

答案 1 :(得分:0)

刚刚开始工作了。有更有效的方法吗?

select imei, reason, ts AS start, (
    select ts
    from events as stops
    where stops.ts > starts.ts
    and reason = 'STOP'
    and stops.user = starts.user
    order by ts desc
    limit 1
) as stop
from events as starts
where reason = 'START'
order by ts
;