在应用开发中,签到功能是提升用户活跃度的常见手段,使用mysql作为存储引擎,我们可以快速实现一个满足基础需求的简易签到系统,不需要引入额外的复杂中间件,开发成本较低。

核心表结构设计
简易签到系统需要两张核心表,分别是用户基础信息表和签到记录表,具体字段设计如下:
用户表 user
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | int | 用户唯一ID,主键自增 |
| username | varchar(50) | 用户名 |
| create_time | datetime | 用户注册时间 |
签到记录表 sign_record
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | int | 记录ID,主键自增 |
| user_id | int | 关联用户ID |
| sign_date | date | 签到日期,格式为YYYY-MM-DD |
| sign_time | datetime | 签到具体时间 |
为了保证同一个用户一天只能签到一次,我们可以给user_id和sign_date添加联合唯一索引,避免重复签到数据产生。
-- 创建联合唯一索引 ALTER TABLE sign_record ADD UNIQUE INDEX idx_user_date (user_id, sign_date);
核心功能实现
用户签到
用户签到时需要先判断当天是否已经签到,如果未签到则插入签到记录,我们可以利用联合唯一索引的特性,通过插入语句的返回值判断是否签到成功。
-- 用户签到,假设用户ID为1,当前日期为2024-05-20 INSERT INTO sign_record (user_id, sign_date, sign_time) VALUES (1, '2024-05-20', NOW());
如果执行该语句返回主键ID,说明签到成功;如果返回唯一索引冲突错误,说明当天已经签到过,需要提示用户重复签到。
查询用户当天签到状态
判断用户当天是否签到,只需要查询签到记录表中对应用户和当天日期的记录是否存在即可。
-- 查询用户ID为1的用户2024-05-20是否签到 SELECT COUNT(*) AS sign_count FROM sign_record WHERE user_id = 1 AND sign_date = '2024-05-20';
如果返回的sign_count大于0,说明已经签到,否则未签到。
统计用户连续签到天数
统计连续签到天数需要按签到日期倒序排列用户的签到记录,然后依次判断日期是否连续,这里可以通过变量实现。
-- 统计用户ID为1的连续签到天数
SELECT COUNT(*) AS continuous_days
FROM (
SELECT
sign_date,
@prev_date := COALESCE(@prev_date, DATE_SUB(sign_date, INTERVAL 1 DAY)) AS prev_date,
@is_continuous := IF(DATEDIFF(sign_date, @prev_date) = 1, 1, 0) AS is_continuous,
@prev_date := sign_date
FROM sign_record, (SELECT @prev_date := NULL) AS init
WHERE user_id = 1
ORDER BY sign_date DESC
) AS temp
WHERE is_continuous = 1;
查询用户签到历史
如果需要展示用户的签到历史列表,直接按时间倒序查询签到记录即可。
-- 查询用户ID为1的最近10条签到记录 SELECT sign_date, sign_time FROM sign_record WHERE user_id = 1 ORDER BY sign_date DESC LIMIT 10;
注意事项
- 签到记录表的
sign_date字段使用date类型,避免存储时分秒导致日期判断出错 - 联合唯一索引可以有效防止重复签到,不需要在业务代码中做额外的重复判断逻辑,减少代码复杂度
- 如果用户量较大,签到记录表的数据会快速增长,可以定期归档历史数据,提升查询效率