统计连续登录天数的核心思路是将“连续”转化为“日期差等于行号差”,通过按用户和差值分组计数识别连续区间,再取最大长度;需确保日期类型正确、去重,并适配不同数据库语法。

统计连续登录天数的核心思路是:把“连续”转化为“日期差等于行号差”,再通过分组识别每一段连续区间,最后取最大长度。
用日期和行号构造连续标识
对每个用户的登录记录按日期排序,生成行号(row_number),再用登录日期减去行号。同一段连续登录中,这个差值是固定的——因为日期每天+1,行号也每天+1,差值恒定。
- 例如:用户在 2024-01-01、01-02、01-03 登录,对应行号 1/2/3,则 date – row_number 都是 2023-12-31
- 只要这个差值相同,就属于同一连续段
按用户和差值分组计数
以 user_id 和上述计算出的差值(记为 group_key)为联合分组依据,统计每组的记录数,即为该连续段的天数。
- sql 示例(mysql / postgresql / SQL Server 均适用):
select user_id, count(*) AS consecutive_days
FROM (
SELECT user_id, login_date,
login_date – INTERVAL ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY login_date) DAY AS group_key
FROM login_log
) t
GROUP BY user_id, group_key
ORDER BY consecutive_days DESC;
获取每个用户的最长连续天数
在外层再套一层聚合,取每个 user_id 对应的最大 consecutive_days 即可。
- 加一句:SELECT user_id, MAX(consecutive_days) AS max_consecutive FROM (…) GROUP BY user_id
- 若只需全局最高纪录(比如谁连续登录最久),可去掉 GROUP BY,直接用 MAX()
注意点和常见坑
实际使用时需留意数据质量和边界情况:
- 确保 login_date 是 DATE 类型,不是 DATETIME;否则需先用 DATE() 截取日期部分
- 同一天多次登录要先去重,否则会干扰行号和连续性判断
- 不同数据库语法略有差异:PostgreSQL 用 login_date – (ROW_NUMBER() – 1),SQL Server 推荐用 DATEADD(day, -ROW_NUMBER()+1, login_date)