让【宝码香车】来帮你解答,本回答参考DeepSeek编写,并整理提供。
如果还有疑问可以点击头像关注私信或评论。如果答案让您满意,请采纳、点赞、关注,非常感谢!
SQL查询连续登录N天的人员解决方案
问题分析
根据问题描述,我们需要查询最近30天内连续登录超过5天的用户。主要难点在于:
- 每个用户每天可能有多次登录记录
- 需要识别连续日期,而不仅仅是统计登录天数
- 连续登录可以发生在30天内的任意时间段
解决方案思路
解决这类连续日期问题,常用的SQL技巧是使用"日期减去行号"的方法。基本思路是:
- 首先获取每个用户每天的登录情况(去重)
- 为每个用户的登录日期分配行号
- 用登录日期减去行号,连续日期的结果会相同
- 统计每个"连续组"的天数
- 筛选出天数大于等于5的记录
具体SQL实现
假设表名为login_records,包含字段user_id和login_time,以下是解决方案:
WITH
-- 获取每个用户每天的登录情况(去重)
daily_logins AS (
SELECT
user_id,
CAST(login_time AS DATE) AS login_date
FROM login_records
WHERE login_time >= DATEADD(day, -30, GETDATE()) -- 最近30天
GROUP BY user_id, CAST(login_time AS DATE)
),
-- 为每个用户的登录日期分配行号
ranked_logins AS (
SELECT
user_id,
login_date,
ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY login_date) AS row_num
FROM daily_logins
),
-- 计算日期减去行号,连续日期的结果相同
grouped_logins AS (
SELECT
user_id,
login_date,
DATEADD(day, -row_num, login_date) AS group_date
FROM ranked_logins
),
-- 统计每个连续组的天数
consecutive_days AS (
SELECT
user_id,
group_date,
COUNT(*) AS days_count,
MIN(login_date) AS start_date,
MAX(login_date) AS end_date
FROM grouped_logins
GROUP BY user_id, group_date
HAVING COUNT(*) >= 5 -- 连续登录5天及以上
)
-- 最终结果
SELECT DISTINCT user_id
FROM consecutive_days
ORDER BY user_id;
代码解释
daily_logins CTE: 将登录时间转换为日期并去重,确保每个用户每天只计一次登录ranked_logins CTE: 为每个用户的登录日期分配连续的行号grouped_logins CTE: 用登录日期减去行号,连续日期的结果会相同consecutive_days CTE: 按用户和group_date分组,计算每组的天数,筛选出连续5天及以上的记录- 最终查询: 返回所有满足条件的用户ID
注意事项
- 根据实际数据库类型,可能需要调整日期函数(如MySQL使用
DATE()而不是CAST(... AS DATE)) - 如果表结构不同,需要相应调整字段名
- 30天的计算方式可以根据需求调整(如自然月或固定30天)
- 如果需要显示连续登录的具体时间段,可以在最终查询中包含
start_date和end_date字段
这种方法高效且通用,适用于大多数SQL数据库(如SQL Server, MySQL, PostgreSQL等)。