SQL:连续天数的计算方法

例如要计算各用户连续登陆天数

数据:
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

你可能感兴趣的:(SQL:连续天数的计算方法)