例如要计算各用户连续登陆天数
数据:
CREATE TABLE IF NOT EXISTS `loadrecord` (
`uid` int(6) unsigned NOT NULL,
`loadtime` varchar(200) NOT NULL,
PRIMARY KEY (`uid`,`loadtime`)
) DEFAULT CHARSET=utf8;
INSERT INTO `loadrecord` (`uid`, `loadtime`) VALUES
('201', '2017/1/1'),
('201', '2017/1/2'),
('202', '2017/1/2'),
('202', '2017/1/3'),
('203', '2017/1/3'),
('201', '2017/1/4'),
('202', '2017/1/4'),
('201', '2017/1/5'),
('202', '2017/1/5'),
('201', '2017/1/6'),
('203', '2017/1/6'),
('203', '2017/1/7');
#第一步
#判断连续的核心是row_number
#因为row_number是连续的
#所以day-row_number,如果值是恒定的,说明也是连续的,反之一定会变化
select uid,(day(loadtime)-row_number() over(partition by uid order by uid) ) AS cnt
from loadrecord;
#第二步
#第一步得到的结果还不是很明显,需要分组用count()计数,取得不同连续值的次数
SELECT uid,count(*) FROM
(
SELECT uid,(DAY(loadtime)-row_number() over(PARTITION BY uid ORDER BY uid) ) AS cnt
FROM loadrecord
) AS a
GROUP BY uid,cnt;
#第三步
#取得最大连续值
#采用类似部门最高薪的方法 select max() group by
SELECT uid, MAX(cnt) FROM
(
SELECT uid,count(*) AS cnt FROM
(
SELECT uid,(DAY(loadtime)-row_number() over(PARTITION BY uid ORDER BY uid) ) AS cnt
FROM loadrecord
) AS a
GROUP BY uid,cnt
) AS b
GROUP BY uid;
另一个例子:
连续出现3次的值
有时候SQL版本不够高
方法:用 DISTINCT 和 WHERE 语句
算法
连续出现的意味着相同数字的 Id 是连着的,由于这题问的是至少连续出现 3 次,我们使用 Logs 并检查是否有 3 个连续的相同数字。
SELECT *
FROM
Logs l1,
Logs l2,
Logs l3
WHERE
l1.Id = l2.Id - 1
AND l2.Id = l3.Id - 1
AND l1.Num = l2.Num
AND l2.Num = l3.Num
Id Num Id Num Id Num
1 1 2 1 3 1
注意:前两列来自 l1 ,接下来两列来自 l2 ,最后两列来自 l3 。
然后我们从上表中选择任意的 Num 获得想要的答案。同时我们需要添加关键字 DISTINCT ,因为如果一个数字连续出现超过 3 次,会返回重复元素。
MySQL
SELECT DISTINCT
l1.Num AS ConsecutiveNums
FROM
Logs l1,
Logs l2,
Logs l3
WHERE
l1.Id = l2.Id - 1
AND l2.Id = l3.Id - 1
AND l1.Num = l2.Num
AND l2.Num = l3.Num