*有一个接口需求,检验是否为稳定的就业用户,通过验证最近六个月是否都交了社保来给出结果:都交了就认为是稳定的就业用户。
所以就先想了一个类似的需求来实现,之后类推即可。*

需求:从日志表查出前三天连续登陆的用户
准备工作

/**日志表**/
CREATE TABLE log_data(
    id VARCHAR(20),
    login_date date,
    details VARCHAR(100)
);
TRUNCATE log_data;
/**测试数据**/
INSERT log_data VALUES('A01','2021-08-10','XX1');
INSERT log_data VALUES('A01','2021-08-11','XX1');
INSERT log_data VALUES('A01','2021-08-11','XX2');
INSERT log_data VALUES('A01','2021-08-12','XX1');
INSERT log_data VALUES('A01','2021-08-13','XX1');

INSERT log_data VALUES('A02','2021-08-08','XX1');
INSERT log_data VALUES('A02','2021-08-09','XX1');
INSERT log_data VALUES('A02','2021-08-11','XX1');
INSERT log_data VALUES('A02','2021-08-12','XX1');

INSERT log_data VALUES('A03','2021-08-11','XX1');
INSERT log_data VALUES('A03','2021-08-11','XX2');
INSERT log_data VALUES('A04','2021-08-12','XX1');

INSERT log_data VALUES('A05','2021-08-06','XX1');
INSERT log_data VALUES('A05','2021-08-07','XX1');
INSERT log_data VALUES('A05','2021-08-08','XX1');

简单实现1.
不包含今天当天

#通用写法
SELECT 
     id,count(1)  
FROM (
    SELECT DISTINCT id,login_date FROM log_data 
    WHERE date(login_date) >= (CURRENT_DATE-3) AND date(login_date) < CURRENT_DATE
)a
GROUP BY id HAVING count(*)>=3

得到的结果id都是符合需求的id。

已知问题:左包还是右包的问题。如果要包含今天当天,那么where语句的第二个条件改为 ‘<=’ ,但是可能会有这种情况,14、15、17号登陆,不算连续登陆,这种情况下可以把where语句的第一个条件改为 ‘>’,也合理,但是必须今天当天(17)登陆了。也就是不能把14,15,16和15,16,17折两种情况都算上,还是需要明确需求。

(推荐)实现2.

WITH tmp AS(
    SELECT
            id
            ,login_date
            ,details
            ,ROW_NUMBER() over(PARTITION BY id) rn2 -- 编号
    FROM (
        SELECT
            id
            ,login_date
            ,details
            ,ROW_NUMBER() over(PARTITION BY id,login_date) rn1
        FROM log_data
    ) t
    WHERE t.rn1=1 -- 去重(一天登录多次)
)

SELECT 
    id
    ,count(1) -- 登录天数连续
FROM (
    SELECT 
        id
        ,login_date
        ,details
        ,DATE_SUB(login_date,INTERVAL rn2 DAY) AS sub -- 计算连续登录,以便分组
    FROM tmp
) ttt 
GROUP BY id,sub HAVING count(1)>=3 AND sub=DATE_SUB(CURRENT_DATE,INTERVAL count(1) DAY) -- 连续登录大于三天且从今天当天算起