当前位置: 首页 > news >正文

SQL182 连续两次作答试卷的最大时间窗

描述

现有试卷作答记录表exam_record(uid用户ID, exam_id试卷ID, start_time开始作答时间, submit_time交卷时间, score得分):

iduidexam_idstart_timesubmit_timescore
1100690032021-09-07 10:01:012021-09-07 10:21:0284
2100690012021-09-01 12:11:012021-09-01 12:31:0189
3100690022021-09-06 10:01:012021-09-06 10:21:0181
4100590022021-09-05 10:01:012021-09-05 10:21:0181
5100590012021-09-05 10:31:012021-09-05 10:51:0181


请计算在2021年至少有两天作答过试卷的人中,计算该年连续两次作答试卷的最大时间窗days_window,那么根据该年的历史规律他在days_window天里平均会做多少套试卷,按最大时间窗和平均做答试卷套数倒序排序。由示例数据结果输出如下:

uiddays_windowavg_exam_cnt
100662.57

解释:用户1006分别在20210901、20210906、20210907作答过3次试卷,连续两次作答最大时间窗为6天(1号到6号),他1号到7号这7天里共做了3张试卷,平均每天3/7=0.428571张,那么6天里平均会做0.428571*6=2.57张试卷(保留两位小数);

用户1005在20210905做了两张试卷,但是只有一天的作答记录,过滤掉。

WITH t2 AS (
SELECT uid,COUNT(start_time) total, -- 用户2021年作答的次数DATEDIFF(MAX(start_time),MIN(start_time))+1  diff_time, -- 头尾作答时间窗 MAX(DATEDIFF(next_time,start_time))+1 days_window -- 最大间隔天数
FROM (SELECT uid,start_time,LEAD(start_time,1)OVER(PARTITION BY uid ORDER BY start_time) AS next_time -- 第二次作答时间FROM exam_recordWHERE YEAR(start_time)=2021 -- 2021年的数据) t1
GROUP BY uid
)
SELECT uid,days_window,ROUND(total* days_window/diff_time,2) avg_exam_cnt
FROM t2
WHERE diff_time>1
ORDER BY days_window DESC,avg_exam_cnt DESC;

🔑 关键代码 & 逐行解释

1. 筛选年份:锁定 2021 年

WHERE YEAR(start_time) = 2021
  • ✅ 只保留 2021 年的答题记录
  • 💡 YEAR() 提取年份,常用于时间分析

2. LEAD():找“下一次”答题时间(核心!)

LEAD(start_time, 1) OVER (PARTITION BY uid ORDER BY start_time) AS next_time
  • ✅ LEAD(列, n):取后面第 n 行的值
  • ✅ PARTITION BY uid:按用户分组
  • ✅ ORDER BY start_time:按时间排序
  • 📌 作用:让每一行都知道“我下次什么时候答题”
  • ⚠️ 最后一次答题的 next_time 是 NULL

示例:

start_timenext_time
2021-01-012021-01-03
2021-01-032021-01-08
2021-01-08NULL

3. 计算最大间隔天数(含首日)

MAX(DATEDIFF(next_time, start_time)) + 1 AS days_window
  • ✅ DATEDIFF(后, 前):两个日期相差多少天
  • ✅ +1:因为“1号到3号”是2天差,但实际跨了3天(1、2、3),所以加1
  • 📌 days_window = 用户最长一次“隔了几天才答题”

4. 计算总活跃天数(首尾跨度)

DATEDIFF(MAX(start_time), MIN(start_time)) + 1 AS diff_time
  • ✅ 从第一次答题到最后一次,总共经历了多少天(含首尾)
  • 📌 比如:1月1日到1月8日 → diff_time = 8

5. 计算总答题次数

COUNT(start_time) AS total
  • ✅ 统计每个用户答题多少次
  • 💡 注意:COUNT 不统计 NULL,所以 next_time 的 NULL 不影响

6. 最终公式:调整后的日均答题估算

ROUND(total * days_window / diff_time, 2) AS avg_exam_cnt
  • ✅ 公式含义:

    “如果用户每次都像他最懒的那次一样间隔,那他平均每天答多少题?”

  • 💡 本质是一个归一化的活跃度评分
  • 📌 ROUND(..., 2):保留两位小数

7. 过滤条件:只看跨天用户

WHERE diff_time > 1
  • ✅ 排除那些只在同一天答题的用户
  • 💡 因为他们没有“间隔”可分析,行为太单一

8. 排序逻辑

ORDER BY days_window DESC, avg_exam_cnt DESC
  • ✅ 先看谁“偷懒最久”(days_window 大)
  • ✅ 再看谁在这种节奏下答得更多(avg_exam_cnt 高)

🎯 输出字段总结

字段含义
uid用户ID
days_window最大答题间隔天数(含首日)
avg_exam_cnt调整后的日均答题频率(评分)

✅ 复习时重点记这几点

  1. LEAD() 是关键:用来计算“下一次时间”
  2. +1 别忘了DATEDIFF 要 +1 才是实际跨度天数
  3. days_window = 最大间隔,反映“最长偷懒时间”
  4. diff_time = 首尾跨度,反映总活跃期
  5. 公式 total × days_window / diff_time 是一个“保守估计”的活跃度
  6. WHERE diff_time > 1 是为了排除单日用户

📌 一句话总结
LEAD 找下一次时间 → 算最大间隔 → 结合总次数和总天数 → 得出一个反映用户“断续学习”行为的评分。

http://www.lryc.cn/news/622145.html

相关文章:

  • 优化网络ROI:专线复用,上云出网一“线”牵!
  • OSCP - Proving Grounds - CVE-2024-25180
  • 技术解读 | 搭建NL2SQL系统需要大模型么?
  • python re正则模块
  • Redis 缓存和 Redis 分布式锁
  • Spring中存在两个相同的Bean是否会报错?
  • PyTorch 训练神经网络模型,并集成到springboot项目中
  • STM32L051同时处理Alarm A和Alarm B中断
  • 朗空量子与 Anolis OS 完成适配,龙蜥获得抗量子安全能力
  • Nginx反向代理Tomcat实战指南
  • 测控一体化闸门驱动灌区信息化升级的核心引擎
  • C++设计模式:类间关系
  • 自定义数据集(pytorchhuggingface)
  • cut、tr、sort 和 uniq 生产典型示例
  • 微服务的编程测评系统11-jmeter-redis-竞赛列表
  • Nginx反向代理与缓存实现
  • 【论文解读】DDRNet:深度双分辨率网络在实时语义分割中的结构与原理全面剖析
  • 51单片机-驱动蜂鸣器模块教程
  • 开源数据发现平台:Amundsen Frontend Service 安装 开发者指南
  • debian13 安装过程 root配置
  • 从 LLM 到自主 Agent:OpenCSG 打造开源 AgenticOps 生态
  • Linux网络基础概念
  • 【RTOS】RT-Thread 进程间通信IPC源码级分析详解
  • [Pyro] 基础构件 | 随机性sample | 可学习参数param | 批量处理plate
  • 【3D图像技术分析及实现】3DGS与深度学习网络结合以实现跨场景迁移的研究调研
  • 电力系统之常见基础概念
  • 【秋招笔试】2025.08.15饿了么秋招机考-第二题
  • [激光原理与应用-285]:理论 - 波动光学 - 无线电磁波的频谱分配
  • [激光原理与应用-287]:理论 - 波动光学 - 电磁波既能承载能量,又能承载信息?
  • 力扣(接雨水)——单调栈