SQL面试题1:连续登陆问题
引言
场景介绍:
许多互联网平台为了提高用户的参与度和忠诚度,会推出各种连续登录奖励机制。例如,游戏平台会给连续登录的玩家发放游戏道具、金币等奖励;学习类 APP 会为连续登录学习的用户提供积分,积分可兑换课程或其他福利。通过这些激励措施,平台希望用户能够养成持续使用产品的习惯,从而提升产品的活跃度和留存率。同时,对于平台运营者来说,分析用户的连续登录数据可以了解用户的使用习惯和忠诚度,进而优化产品功能和运营策略。
题目描述:
假设我们有一个记录用户登录信息的表,表名为 login_table,其中包含两个字段:uid(用户 ID)和 dt(登录日期)。现在需要完成以下三个任务:
- 查询连续登录超过三天的用户:找出在一段时间内,连续登录天数大于三天的用户列表。这有助于平台识别出那些高度活跃且对产品有较高忠诚度的用户,以便进一步进行精细化运营和奖励。
- 查询每个用户连续登录的最大天数:对于每个用户,统计其在所有登录记录中连续登录的最长时间段,这能帮助我们了解不同用户的活跃程度差异,为个性化运营提供数据基础。
- 查询一个用户连续登录的最大天数(可隔一天):在计算用户连续登录天数时,允许中间间隔一天,只要整体登录天数最多,就是我们要找的结果。比如用户在 1、3、5、6 日登录,那么其连续登录的最大天数为 6 天。这种统计方式可以更灵活地评估用户的活跃程度,考虑到了用户可能因为某些特殊情况中断一天登录,但整体仍保持较高的使用频率。
数据准备与代码实现
数据准备
1 2025-01-01
1 2025-01-02
1 2025-01-03
2 2025-01-07
2 2025-01-08
3 2025-01-09
3 2025-01-10
3 2025-01-12
3 2025-01-13
1. 查询连续登录超过三天的用户
思路:
- 用户登录记录编号:利用
row_number()
函数按uid
分区并依dt
升序排序生成序号rn
,实现对各用户登录时间进行排序编号 - 计算连续登录首日:利用
date_add
函数将dt
减去rn
,计算每行对应的连续登录起始日期first_day
。 - 选出连续登录超过三天大用户:利用
group by
按uid
和first_day
分组,结合having
筛选出分组行数大于等于3的记录,实现找出连续登录超三天的用户uid
。
with data as (select 1 as uid,'2025-01-01' as dt union allselect 1 as uid,'2025-01-02' as dt union allselect 1 as uid,'2025-01-03' as dt union allselect 2 as uid,'2025-01-07' as dt union allselect 2 as uid,'2025-01-08' as dt union allselect 3 as uid,'2025-01-09' as dt union allselect 3 as uid,'2025-01-10' as dt union allselect 3 as uid,'2025-01-12' as dt union allselect 3 as uid,'2025-01-13' as dt
),
data2 as (select uid,dt,row_number() over (partition by uid order by dt) rn from data
),
data3 as (select uid,dt,rn,date_add(dt,-rn) as first_day from data2
)
select uid from data3 group by uid,first_day having count(1) >= 3;
2. 查询每个用户连续登录的最大天数
思路:
- 用户登录记录编号:利用窗口函数
row_number()
,按uid
分区并依dt
升序排序生成序号rn
,实现对各用户登录时间进行排序编号。 - 计算连续登录首日:利用
date_add
函数将dt
减去rn
,计算每行对应的连续登录起始日期first_day
。 - 统计分组登录天数:利用
group by
按uid
和first_day
分组,通过count(*)
统计同一组合的天数login_day
,以此统计出每个用户每段连续登录的天数。 - 获取用户最大连续登录天数:再次使用
group by
对uid
进行分组,通过max(login_day)
从每个用户的多段连续登录天数中选出最大值,最终得到每个用户连续登录的最大天数。
with data as (select 1 as uid,'2025-01-01' as dt union allselect 1 as uid,'2025-01-02' as dt union allselect 1 as uid,'2025-01-03' as dt union allselect 2 as uid,'2025-01-07' as dt union allselect 2 as uid,'2025-01-08' as dt union allselect 3 as uid,'2025-01-09' as dt union allselect 3 as uid,'2025-01-10' as dt union allselect 3 as uid,'2025-01-12' as dt union allselect 3 as uid,'2025-01-13' as dt
),
data2 as (select uid,dt,row_number() over (partition by uid order by dt) rn from data
),
data3 as (select uid,dt,rn,date_add(dt,-rn) as first_day from data2
),
data4 as (select uid,first_day,count(*) as login_day from data3 group by uid,first_day)
select uid,max(login_day) from data4 group by uid;
3. 查询一个用户连续登录的最大天数,可以隔一天。解释:1、3、5、6登录则最大登录天数为6天。
思路:
- 查找上次登录时间:利用
lag
函数按uid
分区并依dt
升序排序,实现获取每行记录的上一次登录时间prev_dt
。 - 打标判断连续登录:利用
datediff
函数计算dt
与prev_dt
的时间差,根据差值情况打标flag
,实现区分是否连续登录,如果差值小于2天或者null(表示第一天)标记为0,都则标记为1。 - 计算连续登录标识和:利用
sum
函数按uid
分组并依dt
升序对flag
求和,生成sum_flag
,实现标识连续登录段。 - 计算每组时间差值:利用
datediff
函数对uid
和sum_flag
聚类分组后计算max(dt)
与min(dt)
的差值,实现获取每个分组的时间跨度。 - 获取最大连续登录天数:利用分组和
max
函数选出每个用户的最大时间差值max(diff)+1
,实现得到每个用户连续登录的最大天数max_login
。
核心点:将相差值小于等于2的分到同一组里,然后采用分段思想计算每个分组分段的天数即为连续登录的天数。
with data as (select 1 as uid,'2025-01-01' as dt union allselect 1 as uid,'2025-01-02' as dt union allselect 1 as uid,'2025-01-04' as dt union allselect 2 as uid,'2025-01-07' as dt union allselect 2 as uid,'2025-01-08' as dt union allselect 2 as uid,'2025-01-11' as dt union allselect 2 as uid,'2025-01-13' as dt union allselect 2 as uid,'2025-01-15' as dt union allselect 3 as uid,'2025-01-09' as dt union allselect 3 as uid,'2025-01-10' as dt union allselect 3 as uid,'2025-01-12' as dt union allselect 3 as uid,'2025-01-15' as dt
),
data2 as (select uid,dt,lag(dt, 1) over (partition by uid order by dt) prev_dt from data
),
data3 as (select uid,dt,prev_dt,if(datediff(dt, prev_dt) <= 2 or datediff(dt, prev_dt) is null, 0 ,1) flag from data2
),
data4 as (select uid,dt,prev_dt,flag,sum(flag) over(partition by uid order by dt) as sum_flag from data3
),
data5 as (select uid,datediff(max(dt),min(dt)) diff from data4 group by uid,sum_flag
)
select uid,max(diff)+1 as max_login from data5 group by uid;
知识点总结
1.窗口函数:lag、row_number
https://blog.csdn.net/Ahuuua/article/details/127136611
基本语法:函数名(参数) OVER (PARTITION BY 子句 ORDER BY 子句 ROWS/RANGE子句)
- 函数名:如sum、max、min、count、avg等聚合函数以及lead、lag行比较函数等;
- over: 关键字,表示前面的函数是分析函数,不是普通的集合函数;
- 分组子句:over关键字后面挂号内的内容
lag()比较窗口函数
lag/lead(arg1,arg2,arg3):其中arg1为列名;arg2为偏移值,不能为负,默认为1;arg3超出记录窗口时的默认值,当不指定默认值时,则为null。lag:向前取n行; lead:向后取n行
row_number()排序窗口函数
排序窗口函数的主要作用是为查询结果中的每一行数据生成一个唯一的行号。这个行号是基于特定的排序规则生成的,并且可以根据不同的分组条件进行独立编号。
rank | row_number | dense_rank | |
---|---|---|---|
100 | 1 | 1 | 1 |
100 | 1 | 2 | 1 |
90 | 3 | 3 | 2 |
2. 日期计算函数
日期的三种形式:
DATE
:YYYY-MM-DD,CURRENT_DATE()DATETIME
:YYYY-MM-DD HH:MM:SS、CURRENT_TIMESTAMP()TIMESTAMP
:时间戳,1973-12-30 15:30:00为19731230153000,UNIX_TIMESTAMP()
常见计算函数:DATEDIFF(end,start)
:计算end-start,单位天数TIMESTAMPDIFF(unit,start,end)
:计算end-start,单位unit- unit:second、minute、hour、day、week、month、quarter(季度)、year
DATE_ADD(date, num)
:计算date+num后的时间,num参数表示要增加的时间间隔数量,正数表示增加时间,负数表示减少时间。
select CURRENT_DATE(),CURRENT_TIMESTAMP(),UNIX_TIMESTAMP();
相关文章:

SQL面试题1:连续登陆问题
引言 场景介绍: 许多互联网平台为了提高用户的参与度和忠诚度,会推出各种连续登录奖励机制。例如,游戏平台会给连续登录的玩家发放游戏道具、金币等奖励;学习类 APP 会为连续登录学习的用户提供积分,积分可兑换课程或…...

2Spark Core
2Spark Core 1.RDD 详解1) 为什么要有 RDD?2) RDD 是什么?3) RDD 主要属性 2.RDD-API1) RDD 的创建方式2) RDD 的算子分类3) Transformation 转换算子4) Action 动作算子 3. RDD 的持久化/缓存4. RDD 容错机制 Checkpoint5. RDD 依赖关系1) 宽窄依赖2) 为什么要设计宽窄依赖 …...

linux之进程信号(初识信号,信号的产生)
目录 引入一、初识信号(信号预备知识)1.生活中的信号2.Linux中的信号3.信号进程得出的初步结论 二、信号的产生1.通过终端输入产生信号拓展: 硬件中断2.调用系统函数向进程发信号3.硬件异常产生信号4.软件条件产生信号拓展: 核心转储技术总结一下: 引入 一、初识信…...

基于nginx实现正向代理(linux版本)
介绍 在企业开发环境中,局域网内的设备通常需要通过正向代理服务器访问互联网。正向代理服务器充当中介,帮助客户端请求外部资源并返回结果。局域网内也就是俗称的内网,局域网外的互联网就是外网,在一些特殊场景内,例…...

【蓝牙】win11 笔记本电脑连接 hc-06
文章目录 前言步骤 前言 使用电脑通过蓝牙添加串口 步骤 设置 -> 蓝牙和其他设备 点击 显示更多设备 更多蓝牙设置 COM 端口 -> 添加 有可能出现卡顿,等待一会 传出 -> 浏览 点击添加 hc-06,如果没有则点击 再次搜索 确定 添加成…...

小程序组件 —— 31 事件系统 - 事件绑定和事件对象
小程序中绑定事件和网页开发中绑定事件几乎一致,只不过在小程序不能通过 on 的方式绑定事件,也没有 click 等事件,小程序中绑定事件使用 bind 方法,click 事件也需要使用 tap 事件来进行代替,绑定事件的方式有两种&…...

力扣cf补题-1【算法学习day.94】
前言 ###我做这类文章一个重要的目的还是给正在学习的大家提供方向(例如想要掌握基础用法,该刷哪些题?建议灵神的题单和代码随想录)和记录自己的学习过程,我的解析也不会做的非常详细,只会提供思路和一些关…...

系统学习算法:专题四 前缀和
题目一: 算法原理: 这道题是一维前缀和的模板题,通过这道题我们可以了解什么是前缀和 题意很简单,就是先输入数组个数和查询次数,然后将数组的值放进数组,每次查询给2个数,第一个是起点&#x…...

java 迪米特法则,原理、思想、工作流程、实现细节、稳定性、优缺点、应用场景等
迪米特法则(Law of Demeter,LoD),也被称为“最少知识原则”,是一种指导面向对象设计的原则,旨在减少对象之间的耦合度。以下是对迪米特法则的详细解析。 1. 定义 迪米特法则指出:一个对象应该…...

vue项目引入阿里云svg资源图标
1:生成svg图标 登录阿里云官网 1.1 创建项目组 1.2 从阿里云网站上面获取喜欢的图标加入到已有的项目组 1.3 如果团队有自己的设计师,也可以让设计师上传自己的svg图标到阿里云指定的项目组; 使用的时候,把 资源包下载到本地项…...

存储过程和触发器
目录 1、存储过程 1.1 存储过程的概述 1.2 存储过程的类型 1. 系统存储过程 2. 本地存储过程 3. 临时存储过程 4. 扩展存储过程 1.3 T-SQL创建存储过程 1.4 T-SQL执行存储过程 1.5 T-SQL查看存储过程 1.6 T-SQL修改存储过程 1.7 T-SQL删除存储过程 2、触发器 2.1 …...

《拉依达的嵌入式\驱动面试宝典》—计算机网络篇(二)
《拉依达的嵌入式\驱动面试宝典》—计算机网络篇(二) 你好,我是拉依达。 感谢所有阅读关注我的同学支持,目前博客累计阅读 27w,关注1.5w人。其中博客《最全Linux驱动开发全流程详细解析(持续更新)-CSDN博客》已经是 Linux驱动 相关内容搜索的推荐首位,感谢大家支持。 《…...

【深度学习实战】kaggle 自动驾驶的假场景分类
本次分享我在kaggle中参与竞赛的历程,这个版本是我的第一版,使用的是vgg。欢迎大家进行建议和交流。 概述 判断自动驾驶场景是真是假,训练神经网络或使用任何算法来分类驾驶场景的图像是真实的还是虚假的。 图像采用 RGB 格式并以 JPEG 格式…...

Spring Boot 和微服务:快速入门指南
💖 欢迎来到我的博客! 非常高兴能在这里与您相遇。在这里,您不仅能获得有趣的技术分享,还能感受到轻松愉快的氛围。无论您是编程新手,还是资深开发者,都能在这里找到属于您的知识宝藏,学习和成长…...

qt QPainter setViewport setWindow viewport window
使用qt版本5.15.2 引入viewport和window目的是用于实现QPainter画出来的内容随着窗体伸缩与不伸缩两种情况,以及让QPainter在widget上指定的区域(viewport)进行绘制/渲染(分别对应下方demo1,demo2,demo3)。 setViewpo…...

网络安全面试题汇总(个人经验)
1.谈一下SQL主从备份原理? 答:主将数据变更写入自己的二进制log,从主动去主那里去拉二进制log并写入自己的二进制log,从而自己数据库依据二进制log内容做相应变更。主写从读 2.linux系统中的计划任务crontab配置文件中的五个星星分别代表什么ÿ…...

【网络云SRE运维开发】2025第3周-每日【2025/01/14】小测-【第13章ospf路由协议】理论和实操
文章目录 选择题(10道)理论题(5道)实操题(5道) 【网络云SRE运维开发】2025第3周-每日【2025/01/14】小测-【第12章ospf路由协议】理论和实操 选择题(10道) 在OSPF协议中,…...

FreeType 介绍及 C# 示例
FreeType 是一个开源的字体渲染引擎,用于将字体文件(如 TrueType、OpenType、Type 1 等)转换为位图或矢量图形。它广泛应用于操作系统、图形库、游戏引擎等领域,支持高质量的字体渲染和复杂的文本布局。 FreeType 的核心功能 字体…...

金融项目实战 04|JMeter实现自动化脚本接口测试及持续集成
目录 一、⾃动化测试理论 二、自动化脚本 1、添加断言 1️⃣注册、登录 2️⃣认证、充值、开户、投资 2、可重复执行:清除测试数据脚本按指定顺序执行 1️⃣如何可以做到可重复执⾏? 2️⃣清除测试数据:连接数据库setup线程组 ①明确…...

Linux网络知识——路由表
路由表 1 定义与作用 Linux路由表是一个内核数据结构,用于描述Linux主机与其他网络设备之间的路径,以及如何将数据包从源地址路由到目标地址。路由表的主要作用是指导数据包在网络中的传输路径,确保数据包能够准确、高效地到达目标地址。 …...

浅谈云计算14 | 云存储技术
云存储技术 一、云计算网络存储技术基础1.1 网络存储的基本概念1.2云存储系统结构模型1.1.1 存储层1.1.2 基础管理层1.1.3 应用接口层1.1.4 访问层 1.2 网络存储技术分类 二、云计算网络存储技术特点2.1 超大规模与高可扩展性2.1.1 存储规模优势2.1.2 动态扩展机制 2.2 高可用性…...

AI 编程工具—Cursor进阶使用 阅读开源项目
AI 编程工具—Cursor进阶使用 阅读开源项目 首先我们打开一个最近很火的项目browser-use ,直接从github 上克隆即可 索引整个代码库 这里我们使用@Codebase 这个选项会索引这个代码库,然后我们再选上这个项目的README.md 文件开始提问 @Codebase @README.md 这个项目是用…...

使用 WPF 和 C# 将纹理应用于三角形
此示例展示了如何将纹理应用于三角形,以使场景比覆盖纯色的场景更逼真。以下是为三角形添加纹理的基本步骤。 创建一个MeshGeometry3D对象。像往常一样定义三角形的点和法线。通过向网格的TextureCoordinates集合添加值来设置三角形的纹理坐标。创建一个使用想要显示的纹理的 …...

Elasticsearch搜索引擎(二)
RestClient 基础 前言一、RestAPI1. 初始化 *RestClient*2. 创建索引库3. 删除索引库4. 判断索引库是否存在 二、RestClient操作文档1.新增文档2.查询文档3. 删除文档4. 修改文档5. 批量导入文档 前言 ES官方提供了各种不同语言的客户端用来操作ES,这些客户端的本质…...

unity学习17:unity里的旋转学习,欧拉角,四元数等
目录 1 三维空间里的旋转与欧拉角,四元数 1.1 欧拉角比较符合直观 1.2 四元数 1.3 下面是欧拉角和四元数的一些参考文章 2 关于旋转的这些知识点 2.1 使用euler欧拉角旋转 2.2 使用quaternion四元数,w,x,y,z 2.3 使用quaternion四元数,类 Vector3.zero 这种…...

走出实验室的人形机器人,将复刻ChatGPT之路?
1月7日,在2025年CES电子展现场,黄仁勋不仅展示了他全新的皮衣和采用Blackwell架构的RTX 50系列显卡,更进一步展现了他对于机器人技术领域,特别是人形机器人和通用机器人技术的笃信。黄仁勋认为机器人即将迎来ChatGPT般的突破&…...

如何使用wireshark 解密TLS-SSL报文
目录 前言 原理 操作 前言 现在网站都是https 或者 很多站点都支持 http2。这些站点为了保证数据的安全都通过TLS/SSL 加密过,用wireshark 并不能很好的去解析报文,我们就需要用wireshark去解密这些报文。我主要讲解下mac 在 chrome 怎么配置的&…...

电脑有两张网卡,如何实现同时访问外网和内网?
要是想让一台电脑用两张网卡,既能访问外网又能访问内网,那可以通过设置网络路由还有网卡的 IP 地址来达成。 检查一下网卡的连接 得保证电脑的两张网卡分别连到外网和内网的网络设备上,像路由器或者交换机啥的。 给网卡配上不一样的 IP 地…...

定义:除了Vue内置指令以外的其他 v-开头的指令(需要程序员自行扩展定义)作用:自己定义的指令, 可以封装一些 dom 操作, 扩展
1.自定义指令(directives) 1.用法 定义:除了Vue内置指令以外的其他 v-开头的指令(需要程序员自行扩展定义)作用:自己定义的指令, 可以封装一些 dom 操作, 扩展额外功能 语法: ① 局部注册 ●inserted:被绑…...

SpringBoot错误码国际化
先看测试效果: 文件结构 1.中文和英文的错误消息配置 package com.ldj.mybatisflex.common;import lombok.Getter;/*** User: ldj* Date: 2025/1/12* Time: 17:50* Description: 异常消息枚举*/ Getter public enum ExceptionEnum {//# code命名规则:模…...