2

我有一个带有created_at时间戳的事件表。我想将它们分成相隔 N 秒的事件组,特别是 130 秒。然后对于每个组,我只需要知道最低时间戳和最高时间戳。

这是一些示例数据(忽略时间戳的格式,它是一个日期时间字段):

----------------------
| 编号 | created_at |
----------------------
| 1 | 2013-1-20-08:00 |
| 2 | 2013-1-20-08:01 |
| 3 | 2013-1-20-08:05 |
| 4 | 2013-1-20-08:07 |
| 5 | 2013-1-20-08:09 |
| 6 | 2013-1-20-08:12 |
| 7 | 2013-1-20-08:20 |
----------------------

结果我想得到的是:

-------------------------------------
| 开始时间 | 结束时间 |
-------------------------------------
| 2013-1-20-08:00 | 2013-1-20-08:01 |
| 2013-1-20-08:05 | 2013-1-20-08:09 |
| 2013-1-20-08:12 | 2013-1-20-08:12 |
| 2013-1-20-08:20 | 2013-1-20-08:20 |
-------------------------------------

我已经用谷歌搜索并搜索了表达该问题的所有可能方式并尝试了一段时间,但我无法弄清楚。我已经可以在 Ruby 中做到这一点,我只是想弄清楚是否可以将它移动到数据库级别。如果你很好奇或者它更容易可视化,这是它在 Ruby 中的样子:

groups = SortedSet[*events].divide { |a,b| (a.created_at - b.created_at).abs <= 130 }
groups.map do |group|
  { started_at: group.to_a.first.created_at, ended_at: group.to_a.last.created_at }
end

有谁知道如何在 SQL,特别是 PostgreSQL 中做到这一点?

4

1 回答 1

2

我认为您希望在与前一个差异大于 130 秒时开始每个新分组。您可以使用滞后和日期算术来确定分组的开始位置。然后做一个累积和得到分组:

select Grouping, min(created_at), max(created_at)
from (select t.*, sum(GroupStartFlag) over (order by created_at) as Grouping
      from (select t.*,
                   lag(created_at) over (order by created_at) as prevca,
                   (case when extract(epoch from created_at - lag(created_at) over (order by created_at)) < 130
                         then 0 else 1
                    end) as GroupStartFlag
            from t
           ) t
     ) t
group by Grouping;

最后一步是通过“分组”标识符进行聚合,以获得最早和最晚的日期。

于 2013-08-13T02:55:21.550 回答