Oracle:统计连续次日登录玩家数量的SQL问题排查
解决连续次日登录玩家统计问题
我来帮你排查这个问题哈~先看看你写的SQL里的问题点:
- 子查询
select player_id from player1 group by player_id having count(player_id)>1只是筛选了登录次数≥2的玩家,但完全没判断这些登录日期是否是连续的,这一步就把范围无端扩大了; - 后面的join条件
b.log_in_date in (b.log_in_date,(b.log_in_date+1))其实是恒成立的——因为b.log_in_date肯定等于它自己,所以这个条件相当于没加任何过滤,最终会把所有登录次数≥2的玩家的所有登录记录都查出来,自然返回了9行,和预期不符。
接下来给你两种靠谱的解决方案,都能得到你想要的「2名连续次日登录玩家」的结果:
方法一:使用EXISTS子查询(适配大多数SQL数据库)
核心思路是:找出所有玩家,存在至少一条登录记录的次日也有该玩家的登录记录。
SELECT COUNT(DISTINCT player_id) AS consecutive_login_players FROM player1 p1 WHERE EXISTS ( SELECT 1 FROM player1 p2 WHERE p2.player_id = p1.player_id AND p2.log_in_date = DATE_ADD(p1.log_in_date, INTERVAL 1 DAY) );
注:不同数据库的日期计算语法略有差异,比如PostgreSQL用p1.log_in_date + INTERVAL '1 day',SQL Server用DATEADD(day,1,p1.log_in_date),你可以根据自己的数据库调整。
方法二:使用窗口函数LAG/LEAD(适合支持窗口函数的数据库)
窗口函数可以直接获取同一玩家的下一次登录日期,然后判断是否和当前日期连续:
SELECT COUNT(DISTINCT player_id) AS consecutive_login_players FROM ( SELECT player_id, log_in_date, LEAD(log_in_date) OVER (PARTITION BY player_id ORDER BY log_in_date) AS next_login_date FROM player1 ) t WHERE DATEDIFF(next_login_date, log_in_date) = 1;
这里LEAD函数会按登录日期排序,获取同一玩家的下一次登录时间,再用DATEDIFF判断两天间隔是否为1,最后去重统计符合条件的玩家数即可。
内容的提问来源于stack exchange,提问作者Lara
相关产品推荐
相关产品推荐

