SQL面试题练习 —— 各用户最长的连续登录天数-可间断

目录

  • 1 题目
  • 2 建表语句
  • 3 题解

1 题目


现有各用户的登录记录表t_login_events如下,表中每行数据表达的信息是一个用户何时登录了平台。现要求统计各用户最长的连续登录天数,间断一天也算作连续,例如:一个用户在1,3,5,6登录,则视为连续6天登录。

样例数据

+----------+----------------------+
| user_id  |    login_datetime    |
+----------+----------------------+
| 100      | 2021-12-01 19:00:00  |
| 100      | 2021-12-01 19:30:00  |
| 100      | 2021-12-02 21:01:00  |
| 100      | 2021-12-03 11:01:00  |
| 101      | 2021-12-01 19:05:00  |
| 101      | 2021-12-01 21:05:00  |
| 101      | 2021-12-03 21:05:00  |
| 101      | 2021-12-05 15:05:00  |
| 101      | 2021-12-06 19:05:00  |
| 102      | 2021-12-01 19:55:00  |
| 102      | 2021-12-01 21:05:00  |
| 102      | 2021-12-02 21:57:00  |
| 102      | 2021-12-03 19:10:00  |
| 104      | 2021-12-04 21:57:00  |
| 104      | 2021-12-02 22:57:00  |
| 105      | 2021-12-01 10:01:00  |
+----------+----------------------+

期望结果

+----------+---------------+
| user_id  | max_log_days  |
+----------+---------------+
| 100      | 3             |
| 101      | 6             |
| 102      | 3             |
| 104      | 3             |
| 105      | 1             |
+----------+---------------+

2 建表语句


--建表语句

create table if not exists t_login_events
(
    user_id        int comment '用户id',
    login_datetime string comment '登录时间'
)
    comment '直播间访问记录';
--数据插入
INSERT overwrite table t_login_events
VALUES (100, '2021-12-01 19:00:00'),
       (100, '2021-12-01 19:30:00'),
       (100, '2021-12-02 21:01:00'),
       (100, '2021-12-03 11:01:00'),
       (101, '2021-12-01 19:05:00'),
       (101, '2021-12-01 21:05:00'),
       (101, '2021-12-03 21:05:00'),
       (101, '2021-12-05 15:05:00'),
       (101, '2021-12-06 19:05:00'),
       (102, '2021-12-01 19:55:00'),
       (102, '2021-12-01 21:05:00'),
       (102, '2021-12-02 21:57:00'),
       (102, '2021-12-03 19:10:00'),
       (104, '2021-12-04 21:57:00'),
       (104, '2021-12-02 22:57:00'),
       (105, '2021-12-01 10:01:00');

3 题解


  1. 数据去重
select user_id,
       to_date(login_datetime) as login_date
from t_login_events
group by user_id, to_date(login_datetime)

执行结果

+----------+-------------+
| user_id  | login_date  |
+----------+-------------+
| 100      | 2021-12-01  |
| 100      | 2021-12-02  |
| 100      | 2021-12-03  |
| 101      | 2021-12-01  |
| 101      | 2021-12-03  |
| 101      | 2021-12-05  |
| 101      | 2021-12-06  |
| 102      | 2021-12-01  |
| 102      | 2021-12-02  |
| 102      | 2021-12-03  |
| 104      | 2021-12-02  |
| 104      | 2021-12-04  |
| 105      | 2021-12-01  |
+----------+-------------+
  1. 计算日期差

根据用户分组,使用lag函数获得当前行的上一行数据中的日期,使用datediff函数判断日期当期日期与上一行日期的时间差。

select user_id,
       login_date,
       lag(login_date, 1, null) over (partition by user_id order by login_date asc)                       as lag_log_date,
       datediff(login_date, lag(login_date, 1, null) over (partition by user_id order by login_date asc)) as date_diff
from (select user_id,
             to_date(login_datetime) as login_date
      from t_login_events
      group by user_id, to_date(login_datetime)) t1

执行结果

+----------+-------------+---------------+------------+
| user_id  | login_date  | lag_log_date  | date_diff  |
+----------+-------------+---------------+------------+
| 100      | 2021-12-01  | NULL          | NULL       |
| 100      | 2021-12-02  | 2021-12-01    | 1          |
| 100      | 2021-12-03  | 2021-12-02    | 1          |
| 101      | 2021-12-01  | NULL          | NULL       |
| 101      | 2021-12-03  | 2021-12-01    | 2          |
| 101      | 2021-12-05  | 2021-12-03    | 2          |
| 101      | 2021-12-06  | 2021-12-05    | 1          |
| 102      | 2021-12-01  | NULL          | NULL       |
| 102      | 2021-12-02  | 2021-12-01    | 1          |
| 102      | 2021-12-03  | 2021-12-02    | 1          |
| 104      | 2021-12-02  | NULL          | NULL       |
| 104      | 2021-12-04  | 2021-12-02    | 2          |
| 105      | 2021-12-01  | NULL          | NULL       |
+----------+-------------+---------------+------------+
  1. 判断是否连续,累积求和得到分组id

根据date_diff结果判断是否连续,如果date_diff <= 2则认为连续 我们给赋值为0,否则不连续,赋值为1。

select user_id,
       login_date,
       lag_log_date,
       date_diff,
       sum(if(date_diff <= 2, 0, 1)) over (partition by user_id order by login_date asc) as group_id
from (select user_id,
             login_date,
             lag(login_date, 1, null) over (partition by user_id order by login_date asc)  as lag_log_date,
             datediff(login_date, lag(login_date, 1, null)
                                      over (partition by user_id order by login_date asc)) as date_diff
      from (select user_id,
                   to_date(login_datetime) as login_date
            from t_login_events
            group by user_id, to_date(login_datetime)) t1) t2

执行结果

+----------+-------------+---------------+------------+-----------+
| user_id  | login_date  | lag_log_date  | date_diff  | group_id  |
+----------+-------------+---------------+------------+-----------+
| 100      | 2021-12-01  | NULL          | NULL       | 1         |
| 100      | 2021-12-02  | 2021-12-01    | 1          | 1         |
| 100      | 2021-12-03  | 2021-12-02    | 1          | 1         |
| 101      | 2021-12-01  | NULL          | NULL       | 1         |
| 101      | 2021-12-03  | 2021-12-01    | 2          | 1         |
| 101      | 2021-12-05  | 2021-12-03    | 2          | 1         |
| 101      | 2021-12-06  | 2021-12-05    | 1          | 1         |
| 102      | 2021-12-01  | NULL          | NULL       | 1         |
| 102      | 2021-12-02  | 2021-12-01    | 1          | 1         |
| 102      | 2021-12-03  | 2021-12-02    | 1          | 1         |
| 104      | 2021-12-02  | NULL          | NULL       | 1         |
| 104      | 2021-12-04  | 2021-12-02    | 2          | 1         |
| 105      | 2021-12-01  | NULL          | NULL       | 1         |
+----------+-------------+---------------+------------+-----------+
  1. 按照用户和group_id 分组,计算每次连续登陆的天数,再根据用户分组计算最大连续天数

首先根据user_id和group_id分组,用datediff计算出出最大登陆日期和最小登陆日期,两者做差+1 得到每次连续登陆的天数。然后按照用户分组,使用max()计算每个用户最大连续天数。

select user_id,
       max(log_days) as max_log_days
from (select user_id,
             group_id,
             datediff(max(login_date), min(login_date)) + 1 as log_days
      from (select user_id,
                   login_date,
                   lag_log_date,
                   date_diff,
                   sum(if(date_diff <= 2, 0, 1)) over (partition by user_id order by login_date asc) as group_id
            from (select user_id,
                         login_date,
                         lag(login_date, 1, null) over (partition by user_id order by login_date asc)  as lag_log_date,
                         datediff(login_date, lag(login_date, 1, null)
                                                  over (partition by user_id order by login_date asc)) as date_diff
                  from (select user_id,
                               to_date(login_datetime) as login_date
                        from t_login_events
                        group by user_id, to_date(login_datetime)) t1) t2) t3
      group by user_id,
               group_id) t4
group by user_id

执行结果

+----------+---------------+
| user_id  | max_log_days  |
+----------+---------------+
| 100      | 3             |
| 101      | 6             |
| 102      | 3             |
| 104      | 3             |
| 105      | 1             |
+----------+---------------+

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C51单片机程序及仿真(加减器)

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…

AndroidKille更新apktool插件-cnblog

AndroidKiller不更新插件容易报错 apktool插件更新 网址 Releases iBotPeaches/Apktool (github.com) 找到apktool管理器 填入apktool位置&#xff0c;并输入apktool名字 选择默认的apktool版本 x掉&#xff0c;退出重启 可以看到反编译完成了 dex2jar 更新 网址 Release…

数据库-多表设计 多表查询

多表设计 一对多 一对多关系实现&#xff1a;在数据库表中多的一方&#xff0c;添加字段&#xff0c;来关联一的一方的主键 外键约束 -- 创建表时指定 create table 表名(字段名 数据类型,...[constraint] [外键名称] foreign key (外键字段名) references 主表…

帕金森患者饮食小贴士 满满的爱与关怀哦!

&#x1f34e; 首先&#xff0c;要多吃水果和蔬菜&#xff01;新鲜蔬果富含维生素和矿物质&#xff0c;对神经系统有很好的保护作用。&#x1f966; 特别是绿叶蔬菜&#xff0c;比如菠菜、生菜&#xff0c;它们都是健康的小天使&#xff01;&#x1f49a; &#x1f372; 其次&a…

vue2-vue3响应式原理

我们先来看一下响应式意味着什么&#xff1f;我们来看一段代码&#xff1a; m有一个初始化的值&#xff0c;有一段代码使用了这个值&#xff1b;那么在m有一个新的值时&#xff0c;这段代码可以自动重新执行&#xff1b; let m 20 console.log(m) console.log(m * 2)m 40上…

政策护航新能源助推绿色经济腾飞

随着全球气候变化问题日益严重&#xff0c;新能源行业的发展成为推动绿色经济腾飞的重要引擎。近年来&#xff0c;各国政府纷纷出台政策支持新能源产业&#xff0c;旨在激发行业活力&#xff0c;促进经济可持续发展。本文将从政策红利的角度&#xff0c;探讨新能源行业发展的现…

lnmp php7 安装ssh2扩展

安装ssh2扩展前必须安装libssh2包 下载地址: wget http://www.libssh2.org/download/libssh2-1.11.0.tar.gzwget http://pecl.php.net/get/ssh2-1.4.tgz &#xff08;这里要换成最新的版本&#xff09; 先安装 libssh2 再安装 SSH2: tar -zxvf libssh2-1.11.0.tar.gzcd libss…

【Linux进阶】ext2文件系统(inode)

1.再谈inode (1) 理解inode&#xff0c;要从文件储存说起。 文件储存在硬盘上&#xff0c;硬盘的最小存储单位叫做"扇区"&#xff08;Sector&#xff09;。每个扇区储存512字节&#xff08;相当于0.5KB&#xff09;。操作系统读取硬盘的时候&#xff0c;不会一个个…

方法引用 异常 file

一.方法引用 1.方法引用概述 eg: 表示引用run1类里面的sxxxx方法 把这个方法当做抽象方法的方法体 &#xff1a;&#xff1a;是方法引用符 //方法引用Integer[] arr{4,3,1,6,2,7,8,5};Arrays.sort(arr,run1::subtraction);System.out.println(Arrays.toString(arr));}publi…

算法金 | 平均数、众数、中位数、极差、方差,标准差、频数、频率 一“统”江湖

大侠幸会&#xff0c;在下全网同名「算法金」 0 基础转 AI 上岸&#xff0c;多个算法赛 Top 「日更万日&#xff0c;让更多人享受智能乐趣」 抱个拳&#xff0c;送个礼 更多内容&#xff0c;见微*公号往期文章&#xff0c;阅读人数已破 10, 000&#xff1a;协方差、方差、标准…

vue3自定义全局指令和局部指令

1.全局指令 el&#xff1a;指令绑定到的DOM元素&#xff0c;可以用于直接操作当前元素&#xff0c;默认传入钩子的就是el参数&#xff0c;例如我们开始实现的focus指令&#xff0c;就是直接操作的元素DOM binding&#xff1a;这是一个对象&#xff0c;包含以下属性&#xff1a;…

vue项目打包部署后 浏览器自动清除缓存问题(解决方法)

vue打包部署后 浏览器缓存问题&#xff0c;导致控制台报错ChunkLoadError: Loading chunk failed的解决方案 一、报错如下&#xff1a; 每次build打包部署到服务器上时&#xff0c;偶尔会出现前端资源文件不能及时更新到最新&#xff0c;浏览器存在缓存问题&#xff0c;这时在…

怎么做外贸推广:10个详细教程和工具

1. 介绍 1.1 什么是外贸推广 外贸推广指的是将产品或服务推广到国际市场的过程。它的主要目的是吸引海外客户&#xff0c;增加销售额&#xff0c;并扩大企业的全球影响力。外贸推广不仅仅是销售产品&#xff0c;它还包括品牌建设、市场研究和客户关系管理。 谷歌外贸推广案例…

WPF 实现 移动带/旋转带 效果

先来看看效果&#xff1a; 接下来说明下实现步骤&#xff1a; 1.定义个背景 <Grid Background"#ffffff"><Border Background"#7f8b99" /></Grid> 2.定义平行四边形 定义一个 宽40 高21的 四边形。然后定义四个点的起始位置 Points …

el-table实现固定列,及解决固定列导致部分滚动条无法拖动的问题

一、el-table实现固定列 当数据量动态变化时&#xff0c;可以为 Table 设置一个最大高度。 通过设置max-height属性为 Table 指定最大高度。此时若表格所需的高度大于最大高度&#xff0c;则会显示一个滚动条。 <div class"zn-filter-table"><!-- 表格--…

zdppy+vue3+antd 实现表格数据渲染

基本用法 <template><a-table :columns"columns" :data-source"data"><template #headerCell"{ column }"><template v-if"column.key name"><span>xxx Name</span></template></temp…

2024年中国陶瓷轴承用氮化硅粉体市场发展现状及重点竞争企业研究

2024年中国陶瓷轴承用氮化硅粉体市场发展现状及重点竞争企业研究 氮化硅是一种硬度高、结构稳定、热膨胀系数小&#xff0c;抗氧化和抗侵蚀性能好的一种的陶瓷材料&#xff0c;可用于制造高性能氮化硅陶瓷结构件、坩埚涂层等。近年来&#xff0c;伴随着机械制造行业进一步向高精…

Google重大更新--解读Android Auto认证4.3

Google在今年五月更新了Android Auto 4.2.2版本&#xff0c;而在2024年7月他们推出了Android Auto 4.3版本&#xff0c;这是自2023年9月以来对Android Auto 4.2版本的一次重大更新。 为了确保合规性和顺利认证&#xff0c;OEM和Tire1必须确保PDK组件版本与正在认证的主机的Rece…

昇思25天学习打卡营第18天 | 基于MobileNetv2的垃圾分类

内容介绍&#xff1a; MobileNet网络是由Google团队于2017年提出的专注于移动端、嵌入式或IoT设备的轻量级CNN网络&#xff0c;相比于传统的卷积神经网络&#xff0c;MobileNet网络使用深度可分离卷积&#xff08;Depthwise Separable Convolution&#xff09;的思想在准确率小…