如何获得分组时间戳的最小值和最大值

ale*_*dam 6 postgresql group-by gaps-and-islands datetime postgresql-9.5

我很想知道如何创建一个视图,以 10 分钟最接近 10 分钟的间隔分组时间戳,并包含每个最小和最大时间戳。

所以一个看起来像这样的表:

| Hero         | timestamp           |

| Batman       | 2016-12-08 12:00:00 |
| Batman       | 2016-12-08 12:07:00 |
| Batman       | 2016-12-08 13:00:00 |
| Batman       | 2016-12-08 14:00:00 |
| Wonder Woman | 2016-12-08 10:15:00 |
| Wonder Woman | 2016-12-08 10:18:00 |
| Wonder Woman | 2016-12-08 10:25:00 |
| Wonder Woman | 2016-12-08 10:30:00 |
Run Code Online (Sandbox Code Playgroud)

会导致这样的观点

| Hero         | start_time          | end_time            |

| Batman       | 2016-12-08 12:00:00 | 2016-12-08 12:07:00 |
| Wonder Woman | 2016-12-08 10:15:00 | 2016-12-08 10:30:00 |
Run Code Online (Sandbox Code Playgroud)

或这个:

| Hero         | start_time          | end_time            |

| Batman       | 2016-12-08 13:00:00 | NULL                |
| Batman       | 2016-12-08 14:00:00 | NULL                |
| Batman       | 2016-12-08 12:00:00 | 2016-12-08 12:07:00 |
| Wonder Woman | 2016-12-08 10:15:00 | 2016-12-08 10:30:00|
Run Code Online (Sandbox Code Playgroud)

任何一种解决方案都可以。

Erw*_*ter 5

10 分钟间隔的光栅

我建议按“小时”和 10 分钟间隔的组合进行分组:

SELECT hero
     , min(timestamp) AS start_time
     , CASE WHEN count(*) > 1 THEN max(timestamp) END AS end_time
FROM   tbl
GROUP  BY hero
     , date_trunc('hour', timestamp)
     , EXTRACT(MINUTE FROM timestamp)::int / 10
ORDER  BY 1, 2;  -- optional
Run Code Online (Sandbox Code Playgroud)

请参阅手册中的日期/时间函数和运算符一章。

EXTRACT(minute FROM timestamp)提取时间的分钟部分 表达式。转换为整数 ( ::int) 后,整数除法 ( / 10) 有效地舍入到 10 分钟间隔 ( 0- 5)。

CASE表达只增加了一个end_time,如果多于一个的行落在相同的10分钟间隔。

我建议不要使用“时间戳”作为标识符。它是标准 SQL 中的保留字,也是 Postgres 中的基本数据类型。

由 10 分钟或更长时间间隔定义的组

如果“组”是由同一英雄的行之间的 10 分钟或更长时间的间隔定义的:

SELECT hero
     , count(*) AS ct  -- optional
     , min(timestamp) AS start_time
     , CASE WHEN count(*) > 1 THEN max(timestamp) END AS end_time
FROM  (
   SELECT hero, timestamp, count(step OR NULL) OVER (ORDER BY hero, timestamp) AS grp
   FROM  (
      SELECT *
           , lag(timestamp) OVER (PARTITION BY hero ORDER BY timestamp)
           < timestamp - interval '10 min' AS step
      FROM   tbl
      ) sub1
   ) sub2
GROUP  BY hero, grp;
Run Code Online (Sandbox Code Playgroud)

详细解释:

db<>fiddle here
旧的 sqlfiddle

  • 取决于你*预期*。我按照您在问题中提到的 10 分钟间隔分组。如果这不是您想要的问题,请提出一个关于如何形成组的确切定义的问题。 (2认同)