按 TimescaleDB/PostgreSQL 中的突发事件分组

Group by bursts of occurences in TimescaleDB/PostgreSQL

这是我在 Whosebug 中的第一个问题,欢迎任何有关如何提出结构良好的问题的建议。

所以,我有一个 TimescaleDB 数据库,它是基于 Postgres 构建的时间序列数据库。它具有其大部分功能,因此如果您不了解 Timescale,那也不是问题。 我有一个 select 声明 returns:

          time          | num_issues |   actor_login
------------------------+------------+------------------
 2015-11-10 01:00:00+01 |          2 | nifl
 2015-12-10 01:00:00+01 |          1 | anandtrex
 2016-01-09 01:00:00+01 |          1 | isaacrg
 2016-02-08 01:00:00+01 |          1 | timbarclay
 2016-06-07 02:00:00+02 |          1 | kcalmes
 2016-07-07 02:00:00+02 |          1 | cassiozen
 2016-08-06 02:00:00+02 |         13 | phae
 2016-09-05 02:00:00+02 |          2 | phae
 2016-10-05 02:00:00+02 |         13 | cassiozen
 2016-11-04 01:00:00+01 |          6 | cassiozen
 2016-12-04 01:00:00+01 |          4 | cassiozen
 2017-01-03 01:00:00+01 |          5 | cassiozen
 2017-02-02 01:00:00+01 |          8 | cassandraoid
 2017-03-04 01:00:00+01 |         16 | erquhart
 2017-04-03 02:00:00+02 |          3 | erquhart
 2017-05-03 02:00:00+02 |          9 | erquhart
 2017-06-02 02:00:00+02 |          5 | erquhart
 2017-07-02 02:00:00+02 |          2 | greatwarlive
 2017-08-01 02:00:00+02 |          8 | tech4him1
 2017-08-31 02:00:00+02 |          7 | tech4him1
 2017-09-30 02:00:00+02 |         17 | erquhart
 2017-10-30 01:00:00+01 |          7 | erquhart
 2017-11-29 01:00:00+01 |         12 | erquhart
 2017-12-29 01:00:00+01 |          8 | tech4him1
 2018-01-28 01:00:00+01 |          6 | ragasirtahk

它紧随其后。基本上它 returns 一段时间内的用户名,在本例中为 30 天。 SQL 查询是:

SELECT DISTINCT ON(time_bucket('30 days', created_at))
  time_bucket('30 days', created_at) as time,
  count(id) as num_issues,
  actor_login
FROM
  issues_event
WHERE action = 'opened' AND repo_name='netlify/netlify-cms'
group by time, actor_login
order by time, num_issues DESC

我的问题是,如何检测或分组 actor_login 相等且连续的行。 例如,我想将 cassiozen 从 2016-10-05 分组到 2017-01-03,但不与其他 cassiozen专栏。 我尝试过使用辅助列,使用 window 函数(例如 LAG),但如果没有函数或 do 语句,我认为这是不可能的。 我也尝试过函数,但找不到方法。

我们将不胜感激任何方法、想法或解决方案。

编辑:我显示了我想要的输出。

          time          | num_issues |   actor_login    | actor_group_id
------------------------+------------+------------------+----------------
 2015-11-10 01:00:00+01 |          2 | nifl             |              0
 2015-12-10 01:00:00+01 |          1 | anandtrex        |              1
 2016-01-09 01:00:00+01 |          1 | isaacrg          |              2
 2016-02-08 01:00:00+01 |          1 | timbarclay       |              3
 2016-06-07 02:00:00+02 |          1 | kcalmes          |              4
 2016-07-07 02:00:00+02 |          1 | cassiozen        |              5
 2016-08-06 02:00:00+02 |         13 | phae             |              6
 2016-09-05 02:00:00+02 |          2 | phae             |              6
 2016-10-05 02:00:00+02 |         13 | cassiozen        |              7
 2016-11-04 01:00:00+01 |          6 | cassiozen        |              7
 2016-12-04 01:00:00+01 |          4 | cassiozen        |              7
 2017-01-03 01:00:00+01 |          5 | cassiozen        |              7
 2017-02-02 01:00:00+01 |          8 | cassandraoid     |             12
 2017-03-04 01:00:00+01 |         16 | erquhart         |             13
 2017-04-03 02:00:00+02 |          3 | erquhart         |             13
 2017-05-03 02:00:00+02 |          9 | erquhart         |             13
 2017-06-02 02:00:00+02 |          5 | erquhart         |             13
 2017-07-02 02:00:00+02 |          2 | greatwarlive     |             17
 2017-08-01 02:00:00+02 |          8 | tech4him1        |             18
 2017-08-31 02:00:00+02 |          7 | tech4him1        |             18
 2017-09-30 02:00:00+02 |         17 | erquhart         |             16
 2017-10-30 01:00:00+01 |          7 | erquhart         |             16
 2017-11-29 01:00:00+01 |         12 | erquhart         |             16
 2017-12-29 01:00:00+01 |          8 | tech4him1        |             21
 2018-01-28 01:00:00+01 |          6 | ragasirtahk      |             24

MatBaille的解几乎是完美的。 我只是想像这样对连续的演员进行分组,这样我就可以提取一堆具有 table.

其他属性的指标

您可以使用所谓的“间隙和孤岛”方法

WITH
  sorted AS
(
  SELECT
    *,
    ROW_NUMBER() OVER (                         ORDER BY time)   AS rn,
    ROW_NUMBER() OVER (PARTITION BY actor_login ORDER BY time)   AS rn_actor
  FROM
    your_results
)
SELECT
  *,
  rn - rn_actor  AS actor_group_id
FROM
  sorted

然后 (actor_login, actor_group_id) 的组合会将连续的行组合在一起。

db<>fiddle demo