如何在postgresql表中获得不重叠的不同间隔?

rur96b6h  于 2021-07-26  发布在  Java
关注(0)|答案(1)|浏览(481)

表中有用户会话,我需要打印不同的非重叠会话。

  1. CREATE TABLE SESSIONS(
  2. id serial NOT NULL PRIMARY KEY,
  3. ctn INT NOT NULL,
  4. day DATE NOT NULL,
  5. f_time TIME(0) NOT NULL,
  6. l_time TIME(0) NOT NULL
  7. );
  8. INSERT INTO SESSIONS(id, ctn, day, f_time, l_time)
  9. VALUES
  10. (1, 707, '2019-06-18', '10:48:25', '10:56:17'),
  11. (2, 707, '2019-06-18', '10:48:33', '10:56:17'),
  12. (3, 707, '2019-06-18', '10:53:17', '11:00:49'),
  13. (4, 707, '2019-06-18', '10:54:31', '10:57:37'),
  14. (5, 707, '2019-06-18', '11:03:59', '11:10:39'),
  15. (6, 707, '2019-06-18', '11:04:41', '11:08:02'),
  16. (7, 707, '2019-06-18', '11:11:04', '11:19:39');

sql小提琴
我的table是这样的:

  1. id ctn day f_time l_time
  2. 1 707 2019-06-18 10:48:25 10:56:17
  3. 2 707 2019-06-18 10:48:33 10:56:17
  4. 3 707 2019-06-18 10:53:17 11:00:49
  5. 4 707 2019-06-18 10:54:31 10:57:37
  6. 5 707 2019-06-18 11:03:59 11:10:39
  7. 6 707 2019-06-18 11:04:41 11:08:02
  8. 7 707 2019-06-18 11:11:04 11:19:39

现在我需要不同的不重叠的用户会话,所以它应该给我

  1. 1. start_time: 10:48:25 end_time: 11:00:49 duration: 12min,24 sec
  2. 2. start_time: 11:03:59 end_time: 11:10:39 duration: 6min,40 sec
  3. 3. start_time: 11:11:04 end_time: 11:19:33 duration: 8min,29 sec
mctunoxg

mctunoxg1#

这是一个缺口和孤岛问题。下面是一种使用窗口函数的方法:

  1. select
  2. ctn,
  3. min(f_ts) start_ts,
  4. max(l_ts) end_ts,
  5. max(l_ts) - min(f_ts) duration
  6. from (
  7. select
  8. s.*,
  9. count(*) filter(where f_ts > lag_l_ts) over(partition by ctn order by f_ts) grp
  10. from (
  11. select
  12. s.*,
  13. lag(l_ts) over(partition by ctn order by f_ts) lag_l_ts
  14. from (
  15. select
  16. s.*,
  17. (day + l_time)::timestamp l_ts,
  18. (day + f_time)::timestamp f_ts
  19. from sessions s
  20. ) s
  21. ) s
  22. ) s
  23. group by ctn, grp
  24. order by ctn, start_ts

查询的工作方式如下:
首先,我们从日期和时间部分重建适当的时间戳:以这种方式存储数据会使操作变得不容易(而且它不允许会话在不同的日子中传播)
一个数据是标准化的,我们使用 lag() 获取“上一行”的结束时间戳
然后,我们可以构建“相邻”记录的组:每次开始时间戳大于前一个结束时间戳时,就会启动一个新组
最后一步是聚合
db小提琴演示:

  1. ctn | start_ts | end_ts | duration
  2. --: | :------------------ | :------------------ | :-------
  3. 707 | 2019-06-18 10:48:25 | 2019-06-18 11:00:49 | 00:12:24
  4. 707 | 2019-06-18 11:03:59 | 2019-06-18 11:10:39 | 00:06:40
  5. 707 | 2019-06-18 11:11:04 | 2019-06-18 11:19:39 | 00:08:35
展开查看全部

相关问题