互联网SQL面试题:用户会话时长分析

这是一个基于用户点击信息进行会话时长分析的案例,常见于互联网 App 使用分析。

问题描述

用户的访问记录存储在 user_access 表中,包含用户编号(user_id)以及访问时间(access_time)等信息。以下是一个示例数据:

-- 创建示例表
CREATE TABLE user_access(user_id bigint, access_time timestamp);-- 生成示例数据
INSERT INTO user_access VALUES
(1, '2025-04-30 07:00:00'),
(2, '2025-04-30 07:05:00'),
(2, '2025-04-30 07:10:00'),
(1, '2025-04-30 07:15:00'),
(1, '2025-04-30 07:20:00'),
(1, '2025-04-30 08:00:00'),
(3, '2025-04-30 08:00:00'),
(1, '2025-04-30 08:10:00');

对于同一个用户,如果前后两次操作时间间隔超过 30 分钟,则认为它们属于不同的会话。要求分析每个用户每次会话的开始时间和结束时间,输出结果如下:

在这里插入图片描述

以用户 1 为例,他有两次会话,第一次会话从 7 点开始到 7 点 20 分结束(持续 20 分钟),第二次会话从 8 点开始到 8 点 10 分结束(持续 10 分钟)。

问题解析

基于上面的描述,我们首先需要分析用户每次点击的时间和上一次时间是否间隔超过 30 分钟,超过了表示新会话开始,否则仍然属于上一次会话。为此,我们需要使用一个窗口函数 lag,它可以返回上一条数据的信息:

SELECT user_id, access_time,lag(access_time) OVER (PARTITION BY user_id ORDER BY access_time) AS pre_access_time, -- 上次点击时间CASE WHEN access_time  - INTERVAL '30' MINUTE <= lag(access_time) OVER (PARTITION BY user_id ORDER BY access_time) THEN 0ELSE 1END AS new_session -- 基于每次点击和上次点击时间间隔判断是否新的会话
FROM user_access;user_id|access_time            |pre_access_time        |new_session|
-------+-----------------------+-----------------------+-----------+1|2025-04-30 07:00:00.000|                       |          1|1|2025-04-30 07:15:00.000|2025-04-30 07:00:00.000|          0|1|2025-04-30 07:20:00.000|2025-04-30 07:15:00.000|          0|1|2025-04-30 08:00:00.000|2025-04-30 07:20:00.000|          1|1|2025-04-30 08:10:00.000|2025-04-30 08:00:00.000|          0|2|2025-04-30 07:05:00.000|                       |          1|2|2025-04-30 07:10:00.000|2025-04-30 07:05:00.000|          0|3|2025-04-30 08:00:00.000|                       |          1|

其中,lag 函数分析了每个用户(PARTITION BY user_id)每次点击对应的上一次点击时间(ORDER BY access_time);CASE 表达式基于时间间隔判断是否新的会话开始。

考虑到一个用户可能存在多次会话,我们需要把它们进行编号。基于上面的查询结果,每次新会话开始对应的 new_session 字段都等于 1,其他都等于 0,可以基于这个字段求和生成会话编号:

WITH user_access_session_flag AS ( SELECT user_id, access_time,CASE WHEN access_time  - INTERVAL '30' MINUTE <= lag(access_time) OVER (PARTITION BY user_id ORDER BY access_time) THEN 0ELSE 1END AS new_session -- 基于每次点击和上次点击时间间隔判断是否新的会话FROM user_access
)
SELECT user_id, access_time,sum(new_session) OVER (PARTITION BY user_id ORDER BY access_time) AS session_num -- 基于new_session标识生成每次会话的编号
FROM user_access_session_flag;user_id|access_time            |session_num|
-------+-----------------------+-----------+1|2025-04-30 07:00:00.000|          1|1|2025-04-30 07:15:00.000|          1|1|2025-04-30 07:20:00.000|          1|1|2025-04-30 08:00:00.000|          2|1|2025-04-30 08:10:00.000|          2|2|2025-04-30 07:05:00.000|          1|2|2025-04-30 07:10:00.000|          1|3|2025-04-30 08:00:00.000|          1|

其中,WITH 用于定义通用表表达式,我们可以简单把它理解为一个临时表(user_access_session_flag)。在这里主要是将查询语句模块化,便于我们阅读,否则要使用子查询。

此时,我们已经可以比较清晰地看到每个用户的每次会话信息了。为了生成最终的效果,得到每次会话的开始时间和结束时间,可以基于用户和会话编号再执行一次分组操作:

WITH user_access_session_flag AS ( SELECT user_id, access_time,CASE WHEN access_time  - INTERVAL '30' MINUTE <= lag(access_time) OVER (PARTITION BY user_id ORDER BY access_time) THEN 0ELSE 1END AS new_session -- 基于每次点击和上次点击时间间隔判断是否新的会话FROM user_access
),
user_sessions AS (SELECT user_id, access_time,sum(new_session) OVER (PARTITION BY user_id ORDER BY access_time) AS session_num -- 基于new_session标识生成每次会话的编号FROM user_access_session_flag
)
SELECT user_id, session_num, min(access_time) AS start_time, max(access_time) AS end_time
FROM user_sessions
GROUP BY user_id, session_num
ORDER BY user_id, session_num; -- 分组获取每个用户每次会话的会话开始时间和结束时间user_id|session_num|start_time             |end_time               |
-------+-----------+-----------------------+-----------------------+1|          1|2025-04-30 07:00:00.000|2025-04-30 07:20:00.000|1|          2|2025-04-30 08:00:00.000|2025-04-30 08:10:00.000|2|          1|2025-04-30 07:05:00.000|2025-04-30 07:10:00.000|3|          1|2025-04-30 08:00:00.000|2025-04-30 08:00:00.000|

在以上查询中,我们基于原始数据定义了临时表 user_access_session_flag,然后又基于它定义了临时表 user_sessions,接着基于这个临时表进行分组分析,得到最终结果。

通过这个案例也可以看出,通用表表达式(WITH)编写的代码非常符号我们的阅读理解习惯,推荐大家使用。

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

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

相关文章

前端取经路——现代API探索:沙僧的通灵法术

大家好,我是老十三,一名前端开发工程师。在现代Web开发中,各种强大的API就像沙僧的通灵法术,让我们的应用具备了超乎想象的能力。本文将带你探索从离线应用到实时通信,从多线程处理到3D渲染的九大现代Web API,让你的应用获得"通灵"般的超能力。 在前端取经的第…

window 显示驱动开发-AGP 类型伸缩空间段

AGP 类型的伸缩空间段类似于线性光圈空间段。 但是&#xff0c;内核模式显示微型端口驱动程序&#xff08;KMD&#xff09;不会通过 AGP 类型的伸缩空间段公开 dxgkDdiBuildPagingBuffer 回调函数的DXGK_OPERATION_MAP_APERTURE_SEGMENT和DXGK_OPERATION_UNMAP_APERTURE_SEGMEN…

从零开始学习three.js(15):一文详解three.js中的纹理映射UV

1. UV 映射基础概念 1.1 什么是 UV 坐标&#xff1f; 在三维计算机图形学中&#xff0c;UV 坐标是将二维纹理映射到三维模型表面的坐标系统。UV 中的 U 和 V 分别代表2D纹理空间的水平&#xff08;X&#xff09;和垂直&#xff08;Y&#xff09;坐标轴&#xff0c;与三维空间…

代码复用与分层

1. 代码复用与分层 函数&#xff1a;将常用的代码块封装成函数&#xff0c;提供自己或者团队使用。 库&#xff1a;将代码打包成静态或者动态库&#xff0c;提供出来一个头文件供自己或者团队使用。比如stm32中的HAL库。 框架&#xff1a;通常实现一个完整的系统性的代码&am…

人脸真假检测:SVM 与 ResNet18 的实战对比

在人工智能蓬勃发展的当下&#xff0c;人脸相关技术广泛应用于安防、金融、娱乐等诸多领域。然而&#xff0c;随着人脸合成技术的日益成熟&#xff0c;人脸真假检测成为保障这些应用安全的关键环节。本文将深入探讨基于支持向量机&#xff08;SVM&#xff09;结合局部二值模式&…

类加载器, JVM类加载机制

1.类加载器 Java里有如下几种类加载器 1.引导类加载器 负责加载支撑JVM运行的位于JRE的lib目录下的核心类库&#xff0c;比如rt.jar、charsets.jar等 2.扩展类加载器 负责加载支撑JVM运行的位于JRE的lib目录下的ext扩展目录中的JAR类包 3.应用程序类加载器 负责加载Class…

Hadoop 2.x设计理念解析

目录 一、背景 二、整体架构 三、组件详解 3.1 yarn 3.2 hdfs 四、计算流程 4.1 上传资源到 HDFS 4.2 向 RM 提交作业请求 4.3 RM 调度资源启动 AM 4.4 AM运行用户代码 4.5 NodeManager运行用户代码 4.6 资源释放 五、设计不足 一、背景 有人可能会好奇&#xf…

串口屏调试 1.0

http://wiki.tjc1688.com 先把商家的链接贴过来 淘晶驰T1系列3.2寸串口屏tft液晶屏显示屏HMI触摸屏超12864液晶屏 这是主包的型号 打开这个玩意 有十个基本的功能区 新建工程 在界面的右边&#xff0c;指令一定要写在page前面&#xff0c;这里的波特率等等什么的都可以…

《设计数据密集型应用》——阅读小记

设计数据密集型应用 这本书非常推荐看英语版&#xff0c;如果考过了CET-6就可以很轻松的阅读这本书。 当前计算机软件已经不是单体的时代了&#xff0c;分布式系统&#xff0c;微服务现在是服务端开发的主流&#xff0c;如果没有读过这本书&#xff0c;则强力建议读这本书。 …

【SpringMVC】详解cookie,session及实战

目录 1.前言 2.正文 2.1cookie与session概念 2.2返回cookie参数 2.3设置session 3.小结 1.前言 哈喽大家好吖&#xff0c;今天继续来给大家来分享SpringMVC的学习&#xff0c;今天主要带来的是cookie与session的讲解以及通过postman和fiddler来实战&#xff0c;废话不多…

令狐冲的互联网大厂Java面试之旅

场景描绘&#xff1a;互联网大厂Java面试 在某个阳光明媚的上午&#xff0c;令狐冲来到了风清扬所在的互联网大厂&#xff0c;准备迎接他的Java开发工程师面试。风清扬是一位以严谨和深厚技术功底著称的面试官&#xff0c;令狐冲稍显紧张&#xff0c;但他相信自己的准备。 第…

照片to谷歌地球/奥维地图使用指南

软件介绍 照片to谷歌地球/奥维地图是一款由WTSolutions开发的跨平台图片处理工具&#xff0c;能够将带有GPS信息的照片导入Google Earth&#xff08;谷歌地球&#xff09;或奥维地图。该软件支持Windows、Mac、iOS、Linux和Android系统&#xff0c;无需下载安装&#xff0c;直…

客户端建立一个连接需要占用客户端的端口吗

客户端建立TCP连接时需占用本地端口&#xff0c;具体机制如下&#xff1a; 一、端口占用的必要性 四元组唯一性‌ TCP连接通过‌源IP、源端口、目标IP、目标端口‌四元组唯一标识。客户端发起连接时&#xff0c;必须绑定本地端口以完成通信标识。 动态端口分配‌ 客户端操作…

【生存技能】ubuntu 24.04 如何pip install

目录 原因解决方案说明 在接手一个新项目需要安装python库时弹出了以下提示: 原因 这个报错是因为在ubuntu中尝试直接使用 pip 安装 Python 包到系统环境中&#xff0c;ubuntu 系统 出于稳定性考虑禁止了这种操作 这里的kali是因为这台机器的用户起名叫kali,我也不知道为什么…

智能时代下,水利安全员证如何引领行业变革?

当 5G、AI、物联网等技术深度融入水利工程&#xff0c;传统安全管理模式正经历颠覆性变革。在这场智能化浪潮中&#xff0c;水利安全员证扮演着怎样的角色&#xff1f;又将如何重塑行业人才需求格局&#xff1f; 水利工程智能化转型对安全管理提出新挑战。无人机巡检、智能监测…

TDengine 在智能制造中的核心价值

简介 智能制造与数据库技术的深度融合&#xff0c;已成为现代工业技术进步的一个重要里程碑。随着信息技术的飞速发展&#xff0c;智能制造已经成为推动工业转型升级的关键动力。在这一进程中&#xff0c;数据库技术扮演着不可或缺的角色&#xff0c;它不仅承载着海量的生产数…

微调ModernBERT为大型语言模型打造高效“过滤器”

ModernBERT&#xff08;2024 年 12 月&#xff09;是最近发布的小型语言模型&#xff0c;由 Answer.AI、LightOn 和 HuggingFace 共同开发。它利用了现代优化技术&#xff0c;如用于 8,192 token 上下文窗口的 RoPE 和 GeGLU layers&#xff0c;在保持效率的同时提升性能。jina…

电网拓扑分析:原理与应用

在现代电力系统中&#xff0c;电网拓扑分析是一项至关重要的技术&#xff0c;它为电力系统的安全、稳定和高效运行提供了坚实的基础。电网拓扑描述了电力系统中各元件&#xff08;如发电机、变压器、输电线路、负荷等&#xff09;之间的连接关系&#xff0c;通过拓扑分析&#…

OSPF案例

拓扑图&#xff1a; 要求&#xff1a; 1&#xff0c;R5为ISP&#xff0c;其上只能配置IP地址&#xff1b;R4作为企业边界路由器&#xff0c; 出口公网地址需要通过PPP协议获取&#xff0c;并进行chap认证 2&#xff0c;整个OSPF环境IP基于172.16.0.0/16划分&#xff1b;…

2D横板跳跃游戏笔记(查漏补缺ing...)

1.Compression&#xff08;压缩质量&#xff09;&#xff1a;可以改为None&#xff0c;不压缩的效果最好&#xff0c;但占用内存 2.Filter Mode&#xff08;过滤模式&#xff09;&#xff1a;可以选择Point&#xff08;no filter&#xff09; 3.Pixels Per Unit&#xff1a;是…