已复制
全屏展示
复制代码

SQL实现用户连续登录问题


· 2 min read

查询出连续登录 N 天的用户

查询出连续登录 3 天的用户,表名 login_records 表结构如下:

列名 类型 示例
userid int 1
login_at date 2021-12-14

思路:使用 row_number 解决

  • 去重,即每个用户每一天只会有一天记录
  • row_number() over(partition by userid,login_at order by login_at) ,如果有重复的取出第一个。
  • ROW_NUMBER 按照 userid 分组,在组内按照登陆时间升序编上号。
  • 用日期减去自己的(编号-1),如果日期是连续的话,减去日期以后会得到相同的时间,这个相同的时间就是连续登录的第一天。
  • group by userid,start_at  这里start_at相同表示在同一个连续的时间段,having count(1)控制连续登录的天数。
select userid, start_at, count(1) as cnt
from
(
    select userid, 
        login_at,
        date_sub(login_at, t2.r2-1) as start_at
    from
    ( -- 同一个用户按照时间排序
        select userid, 
            login_at,
            row_number() over(partition by userid order by login_at) as r2
        from
        ( -- 去重,一个用户一天只能有一条记录
            select userid, 
                login_at, 
                row_number() over(partition by userid,login_at order by login_at) as r1
            from login_records
        ) t1
        where r1 = 1
    ) t2
) t3
group by userid, start_at
having count(1) >= 3
order by userid, start_at, cnt

查询连续 N 次都满足相同条件用户

找出连续3次刷抖音都超过40分钟的用户,注意:最近刷抖音可能不是每天都刷,也可能一天会刷多次。表名 douyin_records,表结构如下:

列名 类型 示例
userid int 1
login_at datetime 2021-12-14 00:08:00
play_minutes int 50
  • 思路:使用窗口函数 lag,按照 userid 分区,login_at 升序,找到上一次、上上次的时长,然后在 where 条件里面过滤即可。
SELECT DISTINCT userid
FROM (
         SELECT userid,
                login_at,
                play_minutes,
                LAG(play_minutes, 1, 0) OVER (PARTITION BY userid ORDER BY login_at) AS last_play_minutes,
                LAG(play_minutes, 2, 0) OVER (PARTITION BY userid ORDER BY login_at) AS last_last_play_minutes
         FROM douyin_records
     ) t1
WHERE play_minutes > 40
  AND last_play_minutes > 40
  AND last_last_play_minutes > 40
  
🔗

文章推荐