SQL面试题1:连续登陆问题

引言

场景介绍:

许多互联网平台为了提高用户的参与度和忠诚度,会推出各种连续登录奖励机制。例如,游戏平台会给连续登录的玩家发放游戏道具、金币等奖励;学习类 APP 会为连续登录学习的用户提供积分,积分可兑换课程或其他福利。通过这些激励措施,平台希望用户能够养成持续使用产品的习惯,从而提升产品的活跃度和留存率。同时,对于平台运营者来说,分析用户的连续登录数据可以了解用户的使用习惯和忠诚度,进而优化产品功能和运营策略。

题目描述:

假设我们有一个记录用户登录信息的表,表名为 login_table,其中包含两个字段:uid(用户 ID)和 dt(登录日期)。现在需要完成以下三个任务:

  1. 查询连续登录超过三天的用户:找出在一段时间内,连续登录天数大于三天的用户列表。这有助于平台识别出那些高度活跃且对产品有较高忠诚度的用户,以便进一步进行精细化运营和奖励。
  2. 查询每个用户连续登录的最大天数:对于每个用户,统计其在所有登录记录中连续登录的最长时间段,这能帮助我们了解不同用户的活跃程度差异,为个性化运营提供数据基础。
  3. 查询一个用户连续登录的最大天数(可隔一天):在计算用户连续登录天数时,允许中间间隔一天,只要整体登录天数最多,就是我们要找的结果。比如用户在 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. 查询连续登录超过三天的用户

思路:

  1. 用户登录记录编号:利用row_number()函数按uid分区并依dt升序排序生成序号rn,实现对各用户登录时间进行排序编号
  2. 计算连续登录首日:利用date_add函数将dt减去rn,计算每行对应的连续登录起始日期first_day
  3. 选出连续登录超过三天大用户:利用group byuidfirst_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. 查询每个用户连续登录的最大天数

思路:

  1. 用户登录记录编号:利用窗口函数row_number(),按uid分区并依dt升序排序生成序号rn,实现对各用户登录时间进行排序编号。
  2. 计算连续登录首日:利用date_add函数将dt减去rn,计算每行对应的连续登录起始日期first_day
  3. 统计分组登录天数:利用group byuidfirst_day分组,通过count(*)统计同一组合的天数login_day,以此统计出每个用户每段连续登录的天数。
  4. 获取用户最大连续登录天数:再次使用group byuid进行分组,通过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天。

思路:

  1. 查找上次登录时间:利用lag函数按uid分区并依dt升序排序,实现获取每行记录的上一次登录时间prev_dt
  2. 打标判断连续登录:利用datediff函数计算dtprev_dt的时间差,根据差值情况打标flag,实现区分是否连续登录,如果差值小于2天或者null(表示第一天)标记为0,都则标记为1。
  3. 计算连续登录标识和:利用sum函数按uid分组并依dt升序对flag求和,生成sum_flag,实现标识连续登录段。
  4. 计算每组时间差值:利用datediff函数对uidsum_flag聚类分组后计算max(dt)min(dt)的差值,实现获取每个分组的时间跨度。
  5. 获取最大连续登录天数:利用分组和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()排序窗口函数

排序窗口函数的主要作用是为查询结果中的每一行数据生成一个唯一的行号。这个行号是基于特定的排序规则生成的,并且可以根据不同的分组条件进行独立编号。

rankrow_numberdense_rank
100111
100121
90332

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();

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/66039.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

爬山算法与模拟退火算法的全方面比较

一、基本概念与原理 1. 爬山算法 爬山算法是一种基于启发式的局部搜索算法,通过不断地向当前解的邻域中搜索更优解来逼近全局最优解。它的核心思想是,从当前解出发,在邻域内找到一个使目标函数值更大(或更小)的解作为新的当前解,直到找不到更优的解为止。 2.模拟退火算…

PostgreSQL 超级管理员详解

1. 什么是 PostgreSQL 超级管理员 PostgreSQL 超级管理员&#xff08;superuser&#xff09;是拥有数据库系统最高权限的用户。他们可以执行任何数据库操作&#xff0c;包括但不限于创建和删除数据库、用户、表空间、模式等。超级管理员权限是 PostgreSQL 中权限的最高级别。 …

安装本地测试安装apache-doris

一、安装前规划 我的服务器是三台麒麟服务器,2台跑不起来,这是我本地的,内存分配的也不多。 fe192.168.1.13 主数据库端口9030访问 8Gbe192.168.1.13内存4G 硬盘50be192.168.1.14内存4G 硬盘50be192.168.1.12内存4G 硬盘5013同时安装的fe和be 。 原理:192.168.1.13 服…

GPT(General Purpose Timer)定时器

基本概念&#xff1a; 在嵌入式系统中&#xff0c;General Purpose Timer&#xff08;GPT&#xff09;是一种非常重要的硬件组件&#xff0c;用于提供定时功能。 定义&#xff1a;通用定时器是一种能够提供精确时间测量和控制功能的电子设备或电路模块。它可以产生周期性的时…

集中式架构vs分布式架构

一、集中式架构 如何准确理解集中式架构 1. 集中式架构的定义 集中式架构是一种将系统的所有计算、存储、数据处理和控制逻辑集中在一个或少数几个节点上运行的架构模式。这些中央节点&#xff08;服务器或主机&#xff09;作为系统的核心&#xff0c;负责处理所有用户请求和…

数据挖掘实训:天气数据分析与机器学习模型构建

随着气候变化对各行各业的影响日益加剧&#xff0c;精准的天气预测已经变得尤为重要。降雨预测在日常生活中尤其关键&#xff0c;例如农业、交通和灾害预警等领域。本文将通过机器学习方法&#xff0c;利用历史天气数据预测明天是否会下雨&#xff0c;具体内容包括数据预处理、…

kalilinux - 目录扫描之dirsearch

情景导入 先简单介绍一下dirsearch有啥用。 假如你现在访问一个网站&#xff0c;例如https://www.example.com/ 它是一个电商平台或者其他功能性质的平台。 站在开发者的角度上思考&#xff0c;我们只指导https://www.example.com/ 但不知道它下面有什么文件&#xff0c;文…

关于 ThinkPHP 与 PostgreSQL 结合使用的一些要点

ThinkPHP 是一款流行的 PHP 开发框架&#xff0c;而 PostgreSQL 是功能强大的开源关系型数据库。它们可以结合使用来开发各类应用&#xff0c;以下是关于 ThinkPHP 与 PostgreSQL 结合使用的一些要点&#xff1a; 配置数据库连接 编辑配置文件&#xff1a;在 ThinkPHP 项目中&…

进程同步之信号量机制

信号量机制 信号量机制是一种用于进程同步和互斥的基本工具&#xff0c;特别是在并发编程中&#xff0c;广泛用于控制对共享资源的访问&#xff0c;避免数据竞争和死锁等问题。信号量机制由荷兰计算机科学家Edsger Dijkstra在1965年提出&#xff0c;并在操作系统的进程同步中发…

SOME/IP协议详解 基础解读 涵盖SOME/IP协议解析 SOME/IP通讯机制 协议特点 错误处理机制

车载以太网协议栈总共可划分为五层&#xff0c;分别为物理层&#xff0c;数据链路层&#xff0c;网络层&#xff0c;传输层&#xff0c;应用层&#xff0c;其中今天所要介绍的内容SOME/IP就是一种应用层协议。 SOME/IP协议内容按照AUTOSAR中的描述&#xff0c;我们可以更进一步…

springboot vue uniapp 仿小红书 1:1 还原 (含源码演示)

线上预览: 移动端 http://8.146.211.120:8081/ 管理端 http://8.146.211.120:8088/ 小红书凭借优秀的产品体验 和超高人气 目前成为笔记类产品佼佼者 此项目将详细介绍如何使用Vue.js和Spring Boot 集合uniapp 开发一个仿小红书应用&#xff0c;凭借uniapp 可以在h5 小程序 app…

基于celery的任务管理,本文主要是处理自己的算法,暴露API,管理任务并发,多线程

基于celery的任务管理&#xff0c;本文主要是处理自己的算法&#xff0c;暴露API&#xff0c;管理任务并发&#xff0c;多线程 基本需求描述潜在问题主函数配置文件 基本需求描述 暴露API&#xff0c;供其他人调用算法。方便查看任务状态。因为服务器资源有限&#xff0c;控制…

Java(7)常用的工具类

1.Collections集合工具类 内置了大量对集合操作的静态方法&#xff0c;可以通过类名直接调用方法。 方法的种类&#xff1a;最大值max、最小值min、sort排序...详见API帮助文档 import java.util.ArrayList; import java.util.Collections; import java.util.List;public cl…

【Varnish】:解决 Varnish 7.6 CDN 静态资源缓存失效问题

项目场景&#xff1a; 在一个使用Varnish作为反向代理的Web应用中&#xff0c;我们依赖CDN&#xff08;内容分发网络&#xff09;来缓存静态资源&#xff08;如图片、CSS、JavaScript文件等&#xff09;&#xff0c;以提高全球用户的访问速度并减轻源站服务器的负载。然而&…

理解机器学习中的参数和超参数

在机器学习中&#xff0c;参数和超参数是两个重要但不同的概念&#xff0c;它们共同影响模型的性能和表现。以下是它们的定义和区别&#xff0c;以及如何通俗地理解它们&#xff1a; 1. 参数 定义 参数是模型在训练过程中自动学习到的变量&#xff0c;它们直接决定了模型如何…

Win11右键菜单实现

主要参考Win11 Context Menu Demo 此工程是vs2022编译&#xff0c;vs2019先修改下 base.h 方可编译过 编译好dll以后 拷贝至SparsePackage目录下 生成稀疏包msix 就拿他工程里面的改&#xff0c;编辑AppxManifest.xml&#xff0c;配置都要对&#xff0c;一个不对可能都失败&a…

R.swift库的详细用法

R.swift 是一个 Swift 工具库,它提供了一个自动生成的类 R,使得你可以通过类型安全的方式访问项目中的资源,例如图片、字体、颜色、XIB 文件等。通过 R.swift,你可以避免字符串类型的错误,提升代码的可维护性。 以下是 R.swift 库的详细用法: 1. 安装 R.swift 使用 Sw…

像JSONDecodeError: Extra data: line 2 column 1 (char 134)这样的问题怎么解决

问题介绍 今天处理返回的 JSON 的时候&#xff0c;出现了下面这样的问题&#xff1a; 处理这种问题的时候&#xff0c;首先你要看一下当前的字符串格式是啥样的&#xff0c;比如我查看后发现是下面这样的&#xff1a; 会发现这个字符串中间没有逗号&#xff0c;也就是此时的J…

what?ngify 比 axios 更好用,更强大?

文章目录 前言一、什么是ngify&#xff1f;二、npm安装三、发起请求3.1 获取 JSON 数据3.2 获取其他类型的数据3.3 改变服务器状态3.4 设置 URL 参数3.5 设置请求标头3.6 与服务器响应事件交互3.7 接收原始进度事件3.8 处理请求失败3.9 Http Observables 四、更换 HTTP 请求实现…

Linux Kernel 之十 详解 PREEMPT_RT、Xenomai 的架构、源码、构建及使用

概述 现在的 RTOS 基本可以分为 Linux 阵营和非 Linux 阵营这两大阵营。非 Linux 阵营的各大 RTOS 都是独立发展,使用上也相对独立;而 Linux 阵营则有多种不同的实现方法来改造 Linux 以实现实时性要求。本文我们重点关注 Linux 阵营的实时内核实现方法! 本文我们重点关注 …