Группировка по всплескам вхождений в TimescaleDB / PostgreSQL

это мой первый вопрос в stackoverflow, любые советы о том, как задать хорошо структурированный вопрос, будут приветствоваться.

Итак, у меня есть база данных TimescaleDB, которая представляет собой базы данных временных рядов, построенные на Postgres. Он имеет большинство своих функций, поэтому, если кто-то из вас не знает о Timescale, это не будет проблемой. У меня есть оператор выбора, который возвращает:

          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

И это следует. Обычно он возвращает имя пользователя за период времени, в данном случае 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

Мой вопрос в том, как я могу обнаружить или сгруппировать строки, которые имеют одинаковый пользовательский_логин и являются последовательными. Например, я хотел бы сгруппировать кассиозен с 5 октября 2016 г. по 3 января 2017 г., но не с другим кассиозеном в столбце. Я пробовал использовать дополнительные столбцы, оконные функции, такие как 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 практически идеальное. Я просто хотел сгруппировать таких последовательных акторов, как это, чтобы я мог извлечь кучу показателей с другими атрибутами таблицы.


person RastaDeveloper    schedule 11.05.2021    source источник
comment
Добро пожаловать в SO, это хорошо сформулированный вопрос, спасибо. Не могли бы вы отредактировать его, чтобы добавить еще кое-что? Для примера входных данных, которые вы показали, укажите точные результаты, которые вы ожидаете получить?   -  person MatBailie    schedule 11.05.2021
comment
Что ж, ваша таблица имеет желаемый результат. В противном случае введите желаемый результат.   -  person Meysam Asadi    schedule 11.05.2021


Ответы (1)


Вы можете использовать так называемый подход с промежутками и островками.

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 ‹› демонстрация скрипки

person MatBailie    schedule 11.05.2021
comment
Спасибо, это сработало отлично. - person RastaDeveloper; 11.05.2021
comment
Обновление: я видел некоторые недостатки этого подхода. Несмотря на то, что это хитрое решение, это не всегда работает. Я отредактирую свой пост, чтобы показать, когда это не сработает. - person RastaDeveloper; 11.05.2021
comment
@rastadeveloper Идентификатор - это не просто одно число, это составной ключ (worker_login, субъект_группы_id). См. Демонстрацию скрипта, чтобы узнать, как вы можете использовать этот составной ключ для вывода суррогатного ключа или других агрегатов, статистики и т. Д. (например, в скрипте замените min (rn) на min (временная метка), чтобы узнать, когда группа стартовала.) - person MatBailie; 11.05.2021
comment
Ой, я понимаю, извините. Вы правы, тогда я отредактирую пост. Спасибо. - person RastaDeveloper; 11.05.2021