统计一个月内连续签到7天的用户

如何仅用sql统计一个月内连续签到7天的用户呢?
数据库是mysql!


SELECT user_id
FROM (
    SELECT user_id, sign_date,
           ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY sign_date) AS row_num,
           DATEDIFF(sign_date, 
                    LAG(sign_date) OVER (PARTITION BY user_id ORDER BY sign_date)
                   ) AS diff
    FROM sign_records
    WHERE sign_date >= DATE_SUB(CURRENT_DATE(), INTERVAL 1 MONTH)
) AS subquery
WHERE row_num >= 7 AND diff = 1
GROUP BY user_id
HAVING COUNT(*) = 7;

你可以使用SQL语句来统计一个月内连续签到7天的用户。以下是一个示例的SQL查询:

SELECT user_id
FROM (
    SELECT user_id, 
           date,
           ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY date) AS row_number,
           DATEDIFF(date, '2023-07-01') - ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY date) AS diff
    FROM signin_table
    WHERE date >= '2023-07-01' AND date <= '2023-07-31'
) AS temp
WHERE diff = 7
GROUP BY user_id
HAVING COUNT(*) >= 7;

请确保将上述查询中的signin_table替换为实际存储用户签到记录的表名,user_id替换为实际的用户ID列名,date替换为实际的日期列名。

这个查询使用了窗口函数ROW_NUMBER()和日期差函数DATEDIFF()来计算每个用户的签到顺序和日期差。然后,通过子查询筛选出日期差为7的记录,最后通过GROUP BYHAVING子句来找到连续签到7天的用户。

这个要看你的表结构怎么定义的
一个比较好的思路是,在表结构上定义为
用户id,日期,连续签到数
然后签到的时候插入记录的时候就判断前一天是否签到,如果没有,就连续签到数归0,否则将昨日的数据+1
这样一来,查询就简单了。

表怎么写的

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 你可以参考下这个问题的回答, 看看是否对你有帮助, 链接: https://ask.csdn.net/questions/810256
  • 你也可以参考下这篇文章:你会不会用mysql查询近7个月的数据?没有记录默认为空
  • 你还可以看下sql参考手册中的 MySQL 错误信息和常见的问题 无法连接到[本地]MySQL服务器
  • 您还可以看一下 李杰老师的mysql数据库基础课程中的 数据库管理系统是什么鬼?小节, 巩固相关知识点
  • 除此之外, 这篇博客: 常用SQL语句的优化建议中的 7. 尽量避免在索引列上使用mysql的内置函数 部分也许能够解决你的问题。
  • 以下回答由chatgpt基于相关博客总结生成:

    首先,根据问题描述,我们需要先创建一个表来存储用户的签到记录。假设我们的表名为sign_records,包含以下列: - user_id:用户ID,用于标识每个用户 - sign_date:签到日期,用于记录用户的签到日期

    我们可以使用以下SQL语句创建该表:

    CREATE TABLE sign_records (
        user_id INT,
        sign_date DATE
    );
    

    然后,我们可以通过以下步骤来实现统计连续签到7天的用户:

    1. 选择给定月份内的签到记录:使用SELECT语句从sign_records表中选择给定月份范围内的签到记录。
    SELECT user_id, sign_date
    FROM sign_records
    WHERE sign_date >= '2022-01-01' AND sign_date <= '2022-01-31';
    

    请根据实际情况修改'2022-01-01''2022-01-31'为你所需查询的月份范围。

    1. 按用户分组并按签到日期排序:使用GROUP BY语句按user_id分组,并按sign_date排序,以确保签到记录按用户和日期顺序排列。
    SELECT user_id, sign_date
    FROM sign_records
    WHERE sign_date >= '2022-01-01' AND sign_date <= '2022-01-31'
    GROUP BY user_id, sign_date
    ORDER BY user_id, sign_date;
    
    1. 计算连续签到天数:使用变量和CASE语句来计算每个用户的连续签到天数。当用户的签到日期与上一条记录的签到日期相差不超过1天时,连续签到天数加1;否则,连续签到天数重新计算为1。
    SELECT user_id, sign_date,
        (CASE
            WHEN DATEDIFF(sign_date, @prev_sign_date) <= 1 THEN @consecutive_days := @consecutive_days + 1
            ELSE @consecutive_days := 1
        END) AS consecutive_days,
        @prev_sign_date := sign_date
    FROM (
        SELECT user_id, sign_date
        FROM sign_records
        WHERE sign_date >= '2022-01-01' AND sign_date <= '2022-01-31'
        GROUP BY user_id, sign_date
        ORDER BY user_id, sign_date
    ) AS temp
    CROSS JOIN (SELECT @prev_sign_date := NULL, @consecutive_days := 0) AS vars;
    
    1. 过滤出连续签到7天的用户:将上一步计算得到的结果作为子查询,并在外部查询中筛选出连续签到天数为7的用户。
    SELECT user_id
    FROM (
        SELECT user_id, sign_date,
            (CASE
                WHEN DATEDIFF(sign_date, @prev_sign_date) <= 1 THEN @consecutive_days := @consecutive_days + 1
                ELSE @consecutive_days := 1
            END) AS consecutive_days,
            @prev_sign_date := sign_date
        FROM (
            SELECT user_id, sign_date
            FROM sign_records
            WHERE sign_date >= '2022-01-01' AND sign_date <= '2022-01-31'
            GROUP BY user_id, sign_date
            ORDER BY user_id, sign_date
        ) AS temp
        CROSS JOIN (SELECT @prev_sign_date := NULL, @consecutive_days := 0) AS vars
    ) AS consecutive_days_table
    WHERE consecutive_days = 7;
    

    这个查询语句将返回在给定月份内连续签到7天的用户ID。请根据实际情况修改查询语句中的日期范围。

    希望以上解决方案对你有帮助,如果还有任何问题,请随时提问。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^