bicijinlian 2025-05-12 09:21 采纳率: 100%
浏览 12
已结题

SQL: 查询连续登陆N天的人员

SQL: 查询连续登陆N天的人员

img

项目需求:

查询:“最近一月内,连续登陆超过5天的用户”

条件:

  • 表结构如图

img

  • 每个用户,每天可以有0条或多条登陆记录

  • 最近一个月(或者最近30)内,任意时间段,连续登陆5天都可以; 不一定是最后5天,中间时段也可以;

难点:

咋一听,非常好理解,明白的很。打开 SQL 查询器开始写SQL语句时, 全程懂了。这, “狗吃刺猬无从下嘴”哇!!

友友们,遇到过没,怎么解决哇?给个思路!

每个用户每天可登录多次哦!

注意:AI回答,一律不采纳

  • 因为AI的回答,很难辨别真假
  • 如果能辨别AI的真假,也就不用提问了
  • AI谁都会用,用过之后才提问的
  • 写回答

5条回答 默认 最新

  • 宝码香车 优质创作者: JavaScript技术领域 2025-05-12 09:25
    关注

    让【宝码香车】来帮你解答,本回答参考DeepSeek编写,并整理提供。
    如果还有疑问可以点击头像关注私信或评论。如果答案让您满意,请采纳、点赞、关注,非常感谢!

    SQL查询连续登录N天的人员解决方案

    问题分析

    根据问题描述,我们需要查询最近30天内连续登录超过5天的用户。主要难点在于:

    1. 每个用户每天可能有多次登录记录
    2. 需要识别连续日期,而不仅仅是统计登录天数
    3. 连续登录可以发生在30天内的任意时间段

    解决方案思路

    解决这类连续日期问题,常用的SQL技巧是使用"日期减去行号"的方法。基本思路是:

    1. 首先获取每个用户每天的登录情况(去重)
    2. 为每个用户的登录日期分配行号
    3. 用登录日期减去行号,连续日期的结果会相同
    4. 统计每个"连续组"的天数
    5. 筛选出天数大于等于5的记录

    具体SQL实现

    假设表名为login_records,包含字段user_idlogin_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;
    

    代码解释

    1. daily_logins CTE: 将登录时间转换为日期并去重,确保每个用户每天只计一次登录
    2. ranked_logins CTE: 为每个用户的登录日期分配连续的行号
    3. grouped_logins CTE: 用登录日期减去行号,连续日期的结果会相同
    4. consecutive_days CTE: 按用户和group_date分组,计算每组的天数,筛选出连续5天及以上的记录
    5. 最终查询: 返回所有满足条件的用户ID

    注意事项

    1. 根据实际数据库类型,可能需要调整日期函数(如MySQL使用DATE()而不是CAST(... AS DATE)
    2. 如果表结构不同,需要相应调整字段名
    3. 30天的计算方式可以根据需求调整(如自然月或固定30天)
    4. 如果需要显示连续登录的具体时间段,可以在最终查询中包含start_dateend_date字段

    这种方法高效且通用,适用于大多数SQL数据库(如SQL Server, MySQL, PostgreSQL等)。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(4条)

报告相同问题?

问题事件

  • 系统已结题 5月27日
  • 已采纳回答 5月19日
  • 修改了问题 5月12日
  • 创建了问题 5月12日