说明:刚开始需求只是做一个登陆签到,就奖励积分的一个操作;达到设定的连续签到xx天后,就额外增加xx积分奖励;如果中断签到,则连续签到次数将重新计算;
后来需求变化,需要增加一个提供补签到的功能。因此,需要提供一个查询计算连续签到的算法。
由于需要补签,故需做成日历的形式,可一目了然知道哪些日期未签到,因此需要记录每日签到情况。
表设计关键字段如下:
-- 签到表
CREATE TABLE `t_sign` (
`sign_id` varchar(64) NOT NULL COMMENT '主键ID',
`user_id` varchar(64) NOT NULL COMMENT '用户ID',
`continue_times` int(4) unsigned NOT NULL DEFAULT '0' COMMENT '连续签到次数',
`sign_count` int(4) unsigned NOT NULL DEFAULT '0' COMMENT '签到累计总次数',
`award_count` int(4) unsigned NOT NULL DEFAULT '0' COMMENT '总累计奖励',
`expend_count` int(4) unsigned NOT NULL DEFAULT '0' COMMENT '总累计耗费(因补签造成)'
PRIMARY KEY (`sign_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='签到表';
-- 每日签到表
CREATE TABLE `t_sign_daily` (
`sign_daily_id` varchar(64) NOT NULL COMMENT '主键ID',
`sign_id` varchar(64) NOT NULL COMMENT '签到ID',
`user_id` varchar(64) NOT NULL COMMENT '用户ID',
`award` int(4) NOT NULL DEFAULT '0' COMMENT '本次签到奖励wb(补签扣除wb)',
`sign_time` datetime NOT NULL COMMENT '签到/补签时间',
`sign_type` int(2) unsigned NOT NULL COMMENT '签到类型:1-签到,2-补签'
PRIMARY KEY (`sign_daily_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='每日签到表';
由于计算连续签到次数都是对同一张表的重复循环比较,这种场景比较适用 存储过程进行计算:
CREATE DEFINER=`mysql`@`%` PROCEDURE `proc_sign_continue_times`(IN in_user_id VARCHAR(64), OUT isSinginToday Integer, OUT continueTimes INTEGER)
BEGIN
SET @now = CURRENT_DATE();
SET @count = 0;
SET @isSinginToday = false;
set @row_number = 0;
select count(*) into @count from (
select ABS(datediff(signin_time, @now)) aa , -- 签到时间对比今天的差值
(@row_number:=@row_number + 1) bb -- 排序字段
from t_sign_daily
where user_id = in_user_id and ABS(datediff(sign_time, @now)) > 0 -- 条件排除今天的签到记录
and status = true
ORDER BY aa asc
) T where aa = bb ;
select COUNT(*) into @isSinginToday from t_sign_daily where user_id = in_user_id and status = true and DATEDIFF(signin_time , @now ) = 0 ;-- 今天是否登录
-- 更新连续签到次数
update t_sign set continue_times = (select @count + @isSinginToday) where user_id = in_user_id and status = true;
select @isSinginToday , -- 当天是否签到
@count + @isSinginToday; -- 连续签到n天
END