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主机与其他网络设备之间的路径,以及如何将数据包从源地址路由到目标地址。路由表的主要作用是指导数据包在网络中的传输路径,确保数据包能够准确、高效地到达目标地址。 …...
测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...
7.4.分块查找
一.分块查找的算法思想: 1.实例: 以上述图片的顺序表为例, 该顺序表的数据元素从整体来看是乱序的,但如果把这些数据元素分成一块一块的小区间, 第一个区间[0,1]索引上的数据元素都是小于等于10的, 第二…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...
【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...
Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...
拉力测试cuda pytorch 把 4070显卡拉满
import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试,通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小,增大可提高计算复杂度duration: 测试持续时间(秒&…...
成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...
