2.连续N天登录问题

连续N天登录问题两种思路

思路一

思路分析过程

原始表中只有dt和name列

在这里插入图片描述

--核心代码
->distinct  -- 一个用户一天可能登录多次,所以先去重
-> row_number  -- 增加伪列,分组对登录时间排序  如上图rn列
-> date_sub(dt,rn) as dt2 -- 登录日期与排序需要相减,得到新伪列,如果用户是连续登录的,则该伪列的值应该是一致的,如上图dt2列
-> group by dt2,name  -- 按dt2和用户名分组聚合,得到用户所有连续登录的情况
-> where count(1)>=N天 -- 选出连续登录大于N天的记录
-> distinct name -- 一个用户可能有多次连续登录了指定天,所以继续对结果去重一下
-> count(name) -- 统计有多少用户符合连续登录N天

思路二

思路分析过程

在这里插入图片描述

--核心代码
->distinct  -- 一个用户一天可能登录多次,所以先去重
->date_add(dt,N-1) as date2 -- 得到用户当天登录日期的预期第N-1天后的日期
->lead(dt,N-1) over(partition by userid order by dt) as date3  -- 得到当天登录的实际不同日期的第N-1次后的登录日期
->where date2=date3  -- 预期的与实际的是否相同
->distinct  -- 一个用户可能有多次连续登录了指定天,所以继续对结果去重一下
-> count(name) -- 统计有多少用户符合连续登录N天

例题一:OPPO

以下为用户登陆游戏的日期,用一条SQL语句查询出连续三天登录的人员姓名

namedate
张三2021-01-01
张三2021-01-02
张三2021-01-03
张三2021-01-02
李四2021-01-01
李四2021-01-02
王五2021-01-03
王五2021-01-02
王五2021-01-02
create table game(name string,  `date` string);
insert overwrite table game values
('张三','2021-01-01'),
('张三','2021-01-02'),
('张三','2021-01-03'),
('张三','2021-01-02'),

('张三','2021-01-07'),
('张三','2021-01-08'),
('张三','2021-01-09'),

('李四','2021-01-01'),
('李四','2021-01-02'),
('王五','2021-01-03'),
('王五','2021-01-02'),
('王五','2021-01-02');

-- 方案一
with t1 as ( select distinct  name,`date` from game),
     t2 as ( select *,
                    row_number() over (partition by name order by `date`) rn
         from t1),
     t3 as ( select *,date_sub(`date`,rn) date2 from t2 )
     select distinct name from t3 group by name,date2 having count(1)>=3;
     
     
--方案二
select * from game;
with t1 as (
    select distinct name,`date` from game
),
    t2 as (
        select *,
               date_add(`date`,3-1) as date2,
               lead(`date`,3-1) over(partition by name order by `date`) as date3
          from t1
    )
select distinct name from t2 where date2=date3;

--方案二的写法2
with t1 as (
    select distinct name,`date` from game
),
    t2 as (
        select *,
               lead(`date`,3-1) over(partition by name order by `date`) as date3
          from t1
    )
select distinct name from t2 where datediff(date3,`date`)=2 ;

例题二: 脉脉

用户每日登陆脉脉会访问app不同的模块,现有一个表,记录了每日脉脉活跃用户的uid和不同模块的活跃时长

表形式如下:maimai.dau

duidmoduleactive_duration列说明
2020-01-011jobs324d:活跃的日期uid:用户的唯一编码module:用户活跃模块active_duration:该模块下对应的活跃时长(单位:s)
2020-01-012feeds445
2020-01-013im345
2020-01-022network765
2020-01-023jobs342

在过去一个月内,曾连续两天活跃的用户

-- 建表
-- 表 dau   记录了每日脉脉活跃用户的uid和不同模块的活跃时长
create table dau(d string, uid int, module string, active_duration int);
insert overwrite table dau
values ('2020-01-01', 1, 'jobs', 324),
       ('2020-01-01', 2, 'feeds', 445),
       ('2020-01-01', 3, 'im', 345),
       ('2020-01-02', 2, 'network', 765),
       ('2020-01-02', 3, 'jobs', 342);
select *from dau;


with t1 as ( select distinct  d,uid from dau),
     t2 as ( select *,
                    row_number() over (partition by uid order by d) as rn from t1), -- 增加伪列rn
     t3 as ( select *,
                    date_sub(d,rn) d2 from t2), -- 增加伪列d2
     t4 as ( select uid
             from t3
             where d <= current_date() -- 题目要求是一个月内的,故用where过滤一下
                  and d >= date_sub(current_date(),30)
             group by uid,d2
            having count(1) >= 2)
select distinct uid from t4;

一月内,没有连续两天活跃的用户
在这里插入图片描述

例题三:广州银行

有一张表C_T(列举了部分数据)表示持卡人消费记录,表结构如下:

字段名字段类型字段含义
CARD_NBRVARCHAR2卡号
C_MONTHNUMBER消费月份
C_DATEDATE消费日期
C_TYPEVARCHAR2消费类型
C_ATMNUMBER消费金额

每个月每张卡连续消费的最大天数(如卡在当月只有一次消费则为1)。

连续消费天数:指一段时间内连续每天都有消费,同一天有多笔消费算一天消费,不能跨月份统计。

create table c_t
(
    card_nbr string,
    c_month  string,
    c_date   string,
    c_type   string,
    c_atm    decimal
);
insert overwrite table c_t values
                               (1,'2022-01','2022-01-01','网购',100),
                               (1,'2022-01','2022-01-02','网购',200),
                               (1,'2022-01','2022-01-03','网购',300),
                               (1,'2022-01','2022-01-15','网购',100),
                               (1,'2022-01','2022-01-16','网购',200),
                               (2,'2022-01','2022-01-06','网购',500),
                               (2,'2022-01','2022-01-07','网购',800),
                               (1,'2022-02','2022-02-01','网购',100),
                               (1,'2022-02','2022-02-02','网购',200),
                               (1,'2022-02','2022-02-03','网购',300),
                               (2,'2022-02','2022-02-06','网购',500),
                               (2,'2022-02','2022-02-07','网购',800);
with t1 as (select distinct card_nbr,c_month,c_date from c_t),
     t2 as (select *,row_number() over (partition by card_nbr,c_month order by c_date) rn from t1  ),
     t3 as (select *,date_sub(c_date,rn) dt2 from t2  ),
     -- 此处与之前例题有区别,需要先拿到所有连续消费的情况,而不是直接筛选出连续消费大于N天的记录
     t4 as (select  dt2,card_nbr,c_month,count(1) as cnt from t3 group by dt2,card_nbr,c_month),
     -- 不再是去重,而是取出最大的,因为题目要求的是获取 每个月每张卡连续消费的最大天数
     t5 as ( select *,row_number() over (partition by card_nbr,c_month order by cnt desc) as rn from t4)
select card_nbr,c_month,cnt from t5 where rn=1

在这里插入图片描述

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在 MySQL 中,可以使用以下语句来实现统计连续登录的用户: ``` SELECT user_id FROM login_history WHERE login_time BETWEEN DATE_SUB(NOW(), INTERVAL 3 DAY) AND NOW() GROUP BY user_id HAVING COUNT(*) = 3 ``` 这条查询会搜索在过去三内的所有登录记录,然后分组每个用户的登录记录,最后筛选出登录记录数量等于 3 的用户。 假设你有一张名为 `login_history` 的表,其中包含了登录记录,表结构如下: ``` +---------+------------+ | user_id | login_time | +---------+------------+ | 1 | 2021-01-01 | | 1 | 2021-01-02 | | 1 | 2021-01-03 | | 2 | 2021-01-01 | | 2 | 2021-01-02 | | 3 | 2021-01-01 | | 3 | 2021-01-03 | +---------+------------+ ``` 执行上面的查询后,结果为: ``` +---------+ | user_id | +---------+ | 1 | +---------+ ``` 可以看到,用户 1 在过去三内都登录了,所以被选中。其他用户未被选中,是因为他们在过去三内有一没有登录。 ### 回答2: 要实现统计连续登录的用户,可以通过以下步骤: 1. 首先,创建一个包含用户登录信息的表,可以包括用户ID和登录日期字段。例如,创建一个名为 "login_info" 的表,包含 "user_id" 和 "login_date" 字段。 2. 使用MySQL的时间函数和日期函数来确保只获取最近三内的登录日期。可以使用CURDATE()获取当前日期,使用DATE_SUB()和INTERVAL来计算三前的日期。在查询语句中,使用WHERE子句来筛选出在这个日期范围内的登录记录。 3. 使用GROUP BY子句按照用户ID进行分组,以便根据用户进行统计。 4. 使用HAVING子句来筛选出连续登录的用户。在这个例子中,使用COUNT(*)函数来计算每个用户的登录次数,然后使用条件语句COUNT(*)=3来筛选出登录次数为3的用户,即连续登录。 以下是一个示例查询语句的示例: SELECT user_id FROM login_info WHERE login_date >= DATE_SUB(CURDATE(), INTERVAL 2 DAY) -- 最近三内的登录日期 GROUP BY user_id HAVING COUNT(*) = 3; -- 登录次数为3即连续登录 这样,就可以通过以上步骤来实现统计连续登录的用户。 ### 回答3: 要实现统计连续登陆的用户,可以使用MySQL数据库的日期函数和子查询来实现。 首先,假设用户的登录信息存储在一个表中,包含用户ID(user_id)和登录日期(login_date)两个字段。 可以使用DATE_SUB函数和CURDATE函数结合,查询连续登录记录。具体的SQL查询语句如下: ``` SELECT user_id FROM login_records WHERE login_date >= DATE_SUB(CURDATE(), INTERVAL 2 DAY) GROUP BY user_id HAVING COUNT(DISTINCT login_date) = 3; ``` 解释一下以上查询语句的步骤: 1. `DATE_SUB(CURDATE(), INTERVAL 2 DAY)`用于获取当前日期的前两日期。 2. `WHERE login_date >= DATE_SUB(CURDATE(), INTERVAL 2 DAY)`筛选出登录日期在连续之内的记录。 3. `GROUP BY user_id`按用户ID进行分组。 4. `HAVING COUNT(DISTINCT login_date) = 3`根据分组后的用户ID,统计不重复的登录日期数量为3。 以上查询语句会返回所有连续登陆的用户的ID列表。 需要注意的是,以上的查询语句只能统计连续登录的用户,如果要统计连续N登录的用户,只需将查询语句中的数字2改为N-1即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值