关于连续登录问题

本文探讨如何使用SQL解决连续登陆问题,通过数据去重、自链接表格、row_number()和lag()窗口函数进行分析。文章以牛客网SQL29平均次日留存和SQL58连续自然月练题为例,详细讲解了不同方法的实现思路,包括表链接和窗口函数的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

目录

一、数据源

二、自链接表格的方法

1.对原始数据进行去重处理

2.如和判断是否是连续登陆

三.用row_number()窗口函数优化代码

1.将t1定义为一个子查询因子(临时表)

2.row_number()给t1添加序号

3.ydm-num???

4.count(sub_date)

5.想知道连续登陆时间的起始和结束

四.还可以用lag()窗口函数优化代码

五,牛客网sql29平均次日留存

六,牛客网SQL58任意两个连续自然月练题次数大于1的用户

方法1:表链接

方法2:窗口函数

1.运用with...as建立子查询因子

2.运用子查询嵌套

总结


前言

在牛客网刷题,发现有几道比较难的题都跟连续登陆挂钩

可以连续的天或者连续的月

可以是连续两天,也可以是连续三天,连续n天

可以扩展到连续购买,连续刷题等业务场景

比如sql29 平均次日留存,sql58 任意两个连续自然月练题次数大于1的用户这两个例题

参考b站董旭阳TonyDong董老师的SQL面试题:连续登陆问题思考总结下基本的答题思路

并对这两道牛客网的题目进行整理。


提示:以下是本篇文章正文内容,下面案例可供参考

一、数据源

一张用户登录的表格 u_login

包括用户u_id,登陆日期login_time

二、自链接表格的方法

1.对原始数据进行去重处理

因为一个用户可以在一天登陆好几次,但是只需要每个用户一天有一条记录就可以了,所以需要先去重

想得到的表:

 代码:

select distinct u_id, date(login_time) ymd
from u_login
where login_time between timestamp '2022-10-1 00:00:00' and timestamp '2022-10-31 00:00:00'
#指定一个时间段

知识点:

1,用date()函数提取日期,可以命名为ymd,如果只提取到月就用date_format,命名为ym

2,timestamp时间戳指定一个时间段

3,如果distinct关键字后面有多个字段时,则会对多个字段进行组合去重,只有多个字段组合起来的值是相等的才会被去重

2.如和判断是否是连续登陆

自己跟自己链接,此处以连续登陆三天为例子

t1的时间加一天是t2的时间,t2的时间加一天是t3的时间

想得到的表:

 代码:

select t1.id,t1.ymd,t2.ymd,t3.ymd
from
(select distinct u_id, date(login_time) ymd
from u_login
where login_time between timestamp '2022-10-1 00:00:00' and timestamp '2022-10-31 00:00:00') t1
join 
(select distinct u_id, date(login_time) ymd
from u_login
where login_time between timestamp '2022-10-1 00:00:00' and timestamp '2022-10-31 00:00:00') t2
on t1.u_id=t2.u_id
and t1.ymd=date_add(t2.ymd+interval 1 day)
#此处用datediff()函数也ok,datediff(t2.ymd,t1.ymd)=1
join
(select distinct u_id, date(login_time) ymd
from u_login
where login_time between timestamp '2022-10-1 00:00:00' and timestamp '2022-10-31 00:00:00') t3
on t2.u_id=t3.u_id
and t2.ymd=date_add(t3.ymd+interval 1 day)

知识点:

1,此处连表不用left join,用的是join

原因:用join来连接的话,若第二天没有登陆,则t1的表里的id数据就会过滤掉,过滤掉就表示没有连续登陆所以没关系。跟留存率不一样,第一天登陆(注册)的用户不能过滤,所以留存率连表的时候用的left join。

2,链接条件里面的datediff()和date_add()函数的运用

三.用row_number()窗口函数优化代码

1.将t1定义为一个子查询因子(临时表)

with t1 as
(select distinct u_id, date(login_time) ymd
from u
好的!以下是一道关于“连续登录”的 Hive SQL 问题: --- ### 问题描述: 假设我们有一张用户登录日志表 `user_login`,结构如下: | 字段名 | 类型 | 描述 | |--------------|-------------|----------------| | user_id | STRING | 用户ID | | login_date | DATE | 登录日期 | 数据示例如下: | user_id | login_date | |---------|-------------| | A | 2023-10-01 | | B | 2023-10-01 | | A | 2023-10-02 | | B | 2023-10-04 | | A | 2023-10-05 | | C | 2023-10-06 | **任务:** 编写一条 HiveSQL 查询语句,找出每个用户的最长连续登录天数。 #### 提示: 可以利用窗口函数 `ROW_NUMBER()` 和日期差值计算等技巧完成此题。通过构造辅助列并分组统计来判断连续登录情况。 --- ### 示例解决方案(思路): 以下是解决该问题的一种可能的 SQL 思路: ```sql WITH ranked_logins AS ( SELECT user_id, login_date, ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY login_date) AS rn FROM user_login ), grouped_logins AS ( SELECT user_id, login_date, ADD_DAYS(login_date, -rn) AS grp_key FROM ranked_logins ) SELECT user_id, MAX(consecutive_days) AS max_consecutive_days FROM ( SELECT user_id, COUNT(*) AS consecutive_days FROM grouped_logins GROUP BY user_id, grp_key ) t GROUP BY user_id; ``` 上述查询分为三步: 1. **添加行号 (`ROW_NUMBER`):** 按照 `login_date` 排序生成行号; 2. **构建分组键 (`grp_key`):** 利用日期减去对应的行号得到一个虚拟分组标识符; 3. **按分组计数:** 对每一段连续区间进行计数,并最终选出最大值。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值