位置:首页 > SQL > SQL 子查询如何查询连续登录用户

SQL 子查询如何查询连续登录用户

时间:2026-08-23  |  作者:实验室老王  |  阅读:0

连续登录,是指用户在自然日维度上的登录日期没有断档。比如说,2024 - 01 - 01、01 - 02、01 - 03这就是连续3天;而01 - 01、01 - 02、01 - 04,因为中间缺失了01 - 03,所以就不算连续。它的核心在于识别没有间隙的日期序列,这直接影响到子查询,子查询需要基于“日期 - ROW_NUMBER()”的差值进行分组,而不是简单地判断相邻日期。

SQL子查询如何查询连续登录用户

什么是连续登录的定义,直接影响子查询写法

连续登录不是“每天都有记录”,而是指用户在自然日维度上,登录日期之间没有断档。比如 2024-01-01、01-02、01-03 是连续 3 天;但 01-01、01-02、01-04 就不算连续(缺了 01-03)。很多子查询失败,是因为没先明确这个前提。

常见错误现象:SELECT user_id FROM login_log WHERE DATE(login_time) IN (SELECT DATE(login_time) - INTERVAL 1 DAY FROM login_log)。这种写法存在明显问题,它仅仅是在判断“是否存在前一天”,对于长度大于等于3的连续段,根本无法准确识别,而且很容易就会漏掉首尾部分。

用 ROW_NUMBER() 配合日期差是主流解法

核心思路:对每个用户的登录日期排序,再用日期本身减去序号,同一连续段的“日期 - 序号”结果恒定。这是最稳定、可读性较好、支持 MySQL 8.0+/PostgreSQL/SQL Server 的方案。

实操建议:

  • 先用 ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY DATE(login_time)) 生成递增序号
  • DATE(login_time) 转成天数(如 TO_DAYS(DATE(login_time))CAST(login_time AS DATE)),再减去序号
  • 外层按 user_id 和差值分组,HA VING COUNT(*) >= 3 筛出连续 ≥3 天的用户

示例片段(MySQL):

SELECT user_id
FROM (
SELECT user_id,
 TO_DAYS(CAST(login_time AS DATE)) - 
 ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY CAST(login_time AS DATE)) AS diff
FROM login_log
) t
GROUP BY user_id, diff
HA VING COUNT(*) >= 3;

MySQL 5.7 没有窗口函数?得用自连接或变量模拟

MySQL 5.7 不支持 ROW_NUMBER(),强行用子查询关联会显著变慢,尤其数据量 >10 万行时。这时候变量法更可控,但要注意初始化和执行顺序。

关键点:

  • 必须用 ORDER BY user_id, login_date 确保变量赋值顺序正确
  • 变量不能出现在同一层级的 WHEREHA VING 中,需嵌套一层
  • @rn := IF(@prev = user_id, @rn + 1, 1) 中的 @prev 必须同步更新,否则序号错乱

典型陷阱:SELECT @rn := @rn + 1 在无 ORDER BY 的子查询里行为不可靠,MySQL 可能重排执行顺序。

为什么不能直接用 LEAD/LAG 判断相邻两天

LEAD()LAG() 只能查固定偏移(比如下一天),要查连续 7 天就得写 6 层嵌套,可维护性极差。而且一旦中间某天数据缺失(哪怕只是没触发日志埋点),整条链就断了。

更适合的场景是:快速筛查“是否至少连续 2 天”,而不是统计最长连续天数或筛选 N 天用户。例如:

SELECT DISTINCT user_id
FROM (
SELECT user_id,
 DATE(login_time) AS d1,
 LEAD(DATE(login_time), 1) OVER (PARTITION BY user_id ORDER BY login_time) AS d2
FROM login_log
) t
WHERE DATEDIFF(d2, d1) = 1;

这种写法轻量,但别把它当成通用解法——它不扩展,也不容错。

连续登录的本质是序列分组问题,不是简单相邻判断。真正上线时,日期字段是否含时分秒、时区是否统一、NULL 值怎么处理,都得在子查询里显式约束,不然跑出来的“连续用户”可能一半是脏数据。

免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。

相关文章

更多

精选合集

更多

大家都在玩

热门话题

大家都在看

更多