借鉴了 MySQL 统计连续登录天数的思路和 sql,主要是这篇:
https://zhuanlan.zhihu.com/p/32613190生成测试数据
```
# 创建测试表
CREATE TABLE `tmp_test_lianxu_3` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`DeviceID` int(11) DEFAULT NULL,
`CreateTime` datetime DEFAULT NULL COMMENT '登录时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
# 生成测试数据
INSERT INTO `test`.`tmp_test_lianxu_3` (`id`, `DeviceID`, `CreateTime`) VALUES ('1', '1', '2014-01-01 21:00:00');
INSERT INTO `test`.`tmp_test_lianxu_3` (`id`, `DeviceID`, `CreateTime`) VALUES ('2', '1', '2014-01-02 15:37:57');
INSERT INTO `test`.`tmp_test_lianxu_3` (`id`, `DeviceID`, `CreateTime`) VALUES ('3', '2', '2014-01-01 09:00:00');
INSERT INTO `test`.`tmp_test_lianxu_3` (`id`, `DeviceID`, `CreateTime`) VALUES ('4', '2', '2014-01-02 09:00:00');
INSERT INTO `test`.`tmp_test_lianxu_3` (`id`, `DeviceID`, `CreateTime`) VALUES ('5', '1', '2014-01-04 10:00:00');
INSERT INTO `test`.`tmp_test_lianxu_3` (`id`, `DeviceID`, `CreateTime`) VALUES ('6', '1', '2014-01-05 12:00:00');
INSERT INTO `test`.`tmp_test_lianxu_3` (`id`, `DeviceID`, `CreateTime`) VALUES ('7', '2', '2014-01-10 00:00:00');
INSERT INTO `test`.`tmp_test_lianxu_3` (`id`, `DeviceID`, `CreateTime`) VALUES ('8', '2', '2014-01-11 13:00:00');
INSERT INTO `test`.`tmp_test_lianxu_3` (`id`, `DeviceID`, `CreateTime`) VALUES ('10', '2', '2014-01-12 12:00:00');
INSERT INTO `test`.`tmp_test_lianxu_3` (`id`, `DeviceID`, `CreateTime`) VALUES ('11', '1', '2014-01-08 06:00:00');
INSERT INTO `test`.`tmp_test_lianxu_3` (`id`, `DeviceID`, `CreateTime`) VALUES ('12', '2', '2014-01-11 21:00:00');
INSERT INTO `test`.`tmp_test_lianxu_3` (`id`, `DeviceID`, `CreateTime`) VALUES ('13', '2', '2014-01-15 21:00:00');
INSERT INTO `test`.`tmp_test_lianxu_3` (`id`, `DeviceID`, `CreateTime`) VALUES ('14', '2', '2014-01-17 21:00:00');
INSERT INTO `test`.`tmp_test_lianxu_3` (`id`, `DeviceID`, `CreateTime`) VALUES ('15', '2', '2014-01-19 21:00:00');
INSERT INTO `test`.`tmp_test_lianxu_3` (`id`, `DeviceID`, `CreateTime`) VALUES ('16', '2', '2014-01-21 21:00:00');
INSERT INTO `test`.`tmp_test_lianxu_3` (`id`, `DeviceID`, `CreateTime`) VALUES ('17', '2', '2014-01-26 21:00:00');
INSERT INTO `test`.`tmp_test_lianxu_3` (`id`, `DeviceID`, `CreateTime`) VALUES ('18', '2', '2014-01-28 21:00:00');
INSERT INTO `test`.`tmp_test_lianxu_3` (`id`, `DeviceID`, `CreateTime`) VALUES ('19', '2', '2014-01-30 21:00:00');
INSERT INTO `test`.`tmp_test_lianxu_3` (`id`, `DeviceID`, `CreateTime`) VALUES ('20', '2', '2014-02-16 21:00:00');
INSERT INTO `test`.`tmp_test_lianxu_3` (`id`, `DeviceID`, `CreateTime`) VALUES ('21', '2', '2014-02-13 21:00:00');
```
sql 语句如下
```
SELECT
DeviceID,
# 检查每次巡检记录,如果最近一次巡检时间是 7 天前,那么有效巡检天数+1 ;如果是 7 天内,有效巡检天数+0 ;否则设置为 1
@
cont_day := ( CASE
WHEN ( DATEDIFF(login_dt, @
real_last_dt) > 7 ) THEN (@cont_day + 1)
WHEN ( DATEDIFF(login_dt, @
real_last_dt) <= 7 ) THEN (@cont_day + 0)
ELSE 1
END
) AS days,
@
last_did := DeviceID,
# 判断当前巡检是否为有效巡检(间隔 7 天),是则更新最后有效巡检时间;
# 如果不是则判断是否存在最后有效巡检时间,存在则不变,不存在则设置未当前巡检时间
@
real_last_dt := ( CASE
WHEN ( DATEDIFF(login_dt, @
real_last_dt) > 7 ) THEN login_dt
WHEN ( @
real_last_dt > 0 ) THEN @
real_last_dt ELSE @
last_dt END
) as last_dt,
@
last_dt := login_dt
FROM
( SELECT DeviceID, DATE(CreateTime) AS login_dt FROM tmp_test_lianxu_3
WHERE DeviceID=2 AND CreateTime BETWEEN "2014-01-01" AND "2014-01-31"
ORDER BY DeviceID, CreateTime ) AS t,
( SELECT @
last_did := '', @
last_dt := '', @
real_last_dt := '', @
cont_day := 0 ) AS t1
```
执行后结果如下:(其中 days 即为有效巡检天数)
DeviceID|days|@last_did := DeviceID|last_dt|@last_dt := login_dt
---|---|---|---|---
2|1|2||2014/1/1
2|1|2|2014/1/1|2014/1/2
2|2|2|2014/1/10|2014/1/10
2|2|2|2014/1/10|2014/1/11
2|2|2|2014/1/10|2014/1/11
2|2|2|2014/1/10|2014/1/12
2|2|2|2014/1/10|2014/1/15
2|2|2|2014/1/10|2014/1/17
2|3|2|2014/1/19|2014/1/19
2|3|2|2014/1/19|2014/1/21
2|3|2|2014/1/19|2014/1/26
2|4|2|2014/1/28|2014/1/28
2|4|2|2014/1/28|2014/1/30