SQL:如何搜索连续事件?

时间:2015-08-11 17:25:04

标签: sql postgresql

在PostGRES中,我怎样才能让所有至少有1"事件"连续三个星期?

my_events

id  user_id  created_at
------------------------------------------
1   1234     2015-05-05 22:49:18.345787
2   4567     2015-05-05 22:49:30.343386
3   1234     2015-05-05 22:50:16.465029
...

我尝试过的事情:

步骤1)获取用户举办活动的所有周:

SELECT
user_id,
date_part('year', created_at) AS year,
date_part('week', created_at) AS week,
COUNT(1) AS events
FROM my_events
GROUP BY user_id, date_part('year', created_at), date_part('week', created_at)

步骤2)获取用户举办活动的所有周的计数:

SELECT
user_id,
COUNT(1) AS weeks_with_events
FROM (
  -- Get all weeks where a user had an event.
  SELECT
  user_id,
  date_part('year', created_at) AS year,
  date_part('week', created_at) AS week,
  COUNT(1) AS events
  FROM my_events
  GROUP BY user_id, date_part('year', created_at), date_part('week', created_at)
) a
GROUP BY user_id

不幸的是,这只给了我一个事件的周数,它没有检查它们是否<连续周。

2 个答案:

答案 0 :(得分:0)

我会假设您正在查看此查询:

SELECT user_id, date_part('year', created_at) AS yyyy,
       date_part('week', created_at) AS ww, COUNT(8) AS events
FROM my_events
GROUP BY user_id, date_part('year', created_at), date_part('week', created_at);

虽然不是最通用的解决方案,但最简单的方法可能是使用lead() / lag()

with t as (
      SELECT user_id, date_part('year', created_at) AS yy,
             date_part('week', created_at) AS ww, COUNT(8) AS events
      FROM my_events
      GROUP BY user_id, date_part('year', created_at), date_part('week', created_at)
     )
select user_id, ww
from (select t.*,
             lead(ww, 1) over (partition by user_id order by year, ww) as ww1,
             lead(ww, 2) over (partition by user_id order by year, ww) as ww2
      from t
     ) t
where ww1 = ww + 1 and ww2 = ww + 2;

这将在今年年底出现问题,因为一年中一周的定义重新开始。

编辑:

要处理年终,您希望执行yyyy*52 + ww之类的操作。唉,这几周都没有工作。

相反,请选择一周中正确日期的原始开始日期。然后计算自该日期以来的天数,除以7并截断。这为您提供了一个绝对的周数,与年份无关。从那时起,查询的其余部分几乎相同。

答案 1 :(得分:0)

with x as 
(SELECT
 user_id,
 date_part('year', created_at) AS year,
 date_part('week', created_at) AS week
 FROM my_events)
, y as (select user_id, year, week as curr, 
   coalesce(lead(week) over(partition by user_id,year order by week),0) as nxt,
  coalesce(lag(week) over(partition by user_id,year order by week),0) as prev 
  from x)
  select distinct user_id 
  from y
  where nxt-curr = 1 and curr-prev = 1

您可以尝试这样做,因为您需要用户连续3周至少举办一次活动。前提是如果用户连续3周至少有一个事件,他将在nxt-currcurr-prev为1的情况下发出一行。