如何形成允许给定最大间隙的连续日期组?

Her*_*sas 5 sql postgresql window-functions gaps-and-islands

给定一个像这样的表:

人物ID 联系日 最后联系天数 破折号组
1 2015-02-09 1
1 2015-05-01 81 2
1 2015-05-02 1 2
1 2015-05-03 1 2
1 2015-06-01 29 3
1 2015-08-01 61 4
1 2015-08-04 3 4
1 2015-09-01 28 5
2 2015-05-01 1
2 2015-06-01 31 2
2 2015-07-01 30 3
3 2015-05-01 1
3 2015-05-02 1 1
3 2015-05-04 2 1
3 2015-06-01 28 2
3 2015-06-02 1 2
3 2015-06-06 4 3

另请参阅DB Fiddle 示例

如何识别连续几天的连续但允许最大差距?

数据中的原始列是person_idcontact_day。我想按person_id“streak”(附近的几天)进行分区。到目前为止,我的方法是首先计算自上次联系以来的天数 ( days_last_contact),然后尝试使用它来计算列dash_group,该列标记最大阈值内的行 - 在示例中为 3 天。

我该如何计算dash_group?我days_last_contact通过减法计算contact_day,它是 1-lag,按 person_id 分区并按日期排序)。

SELECT 
  contact_day - lag(contact_day, 1, NULL) 
    OVER (PARTITION BY person_id ORDER BY contact_day ASC) 
    AS days_last_contact
FROM mydata
;
Run Code Online (Sandbox Code Playgroud)

但是我怎样才能使用它来将低于某个阈值的行分组在一起呢days_last_contact?(本例中为 3 天)。因此,在此示例中,dash_group2 for person_id1 标识了临近的 5 月 1 日、2 日和 3 日,但该人的下一个日期是 6 月 1 日,这太远了(距离上次联系已过去 29 天,比阈值为 3),因此它得到一个新的dash_group. 相似地,dash_group 4 将 8 月 1 日和 8 月 4 日分组在一起,因为差异为 3,但在 6 月 2 日和 6 月 6 日(人 3)的情况下,差异为 4,然后将它们分为不同的组。

环顾四周后,我发现了例如这个 SO 问题,他们指向这里的“技巧”#4,这非常hacky,但仅适用于连续日期/无间隙系列,并且我需要允许任意间隙。

Erw*_*ter 6

计算第二个窗口函数中的间隙(大于给定的容差)即可形成您所追求的组数:

SELECT person_id, contact_day
     , count(*) FILTER (WHERE gap > 3) OVER (PARTITION BY person_id ORDER BY contact_day) AS dash_group
FROM  (
   SELECT person_id, contact_day
        , contact_day - lag(contact_day) OVER (PARTITION BY person_id ORDER BY contact_day) AS gap
   FROM   mydata
   ) sub
ORDER  BY person_id, contact_day;  -- optional
Run Code Online (Sandbox Code Playgroud)

db<>在这里摆弄

关于聚合FILTER子句:

它简短而直观,而且通常速度最快。看:

这就是“间隙与岛屿”的经典话题。一旦您知道要查找标签“ ,您就会发现大量相关或几乎相同的问题和答案,例如:

ETC。

我现在做了相应的标记。