当前位置: 首页 > 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.xdnf.cn/news/1304767.html

相关文章:

  • C++第二十课:快递运费计算器 / 黑白配+石头剪刀布小游戏
  • Linux入门(十九)定时备份数据库
  • 第1篇_Go语言初探_环境搭建与HelloWorld
  • 802.11 Wi-Fi 竞争机制深度分析:CSMA/CA 与 DCF
  • 机器学习之PCA降维
  • Scrapy + Django爬虫可视化项目实战(二) 详细版
  • 轴机械臂cad【7张】三维图+设计说明书
  • 25.Linux 聚合链路与软件网桥
  • XXL-TOOL v2.0.0 发布 | Java工具类库
  • AI创业公司分析:Paloma
  • 自定义数据集(pytorchhuggingface)
  • SaltStack 基础
  • 【机器人-基础知识】ROS常见功能架构
  • 考研复习-计算机组成原理-第七章-IO
  • OpenCV---morphologyEx形态学操作
  • Jenkins+Python自动化持续集成详细教程
  • 【JavaEE】多线程 -- 死锁问题
  • Unity输入系统:旧版Input_System
  • 链路聚合与软件网桥配置
  • Mac(一)常用的快捷键整理
  • JavaScript(JS)DOM(四)
  • 【数据分享】2022 年黑龙江省小麦、玉米和水稻幼苗影像数据集
  • Python基础(Flask①)
  • 基于机器学习的赌博网站识别系统设计与实现
  • 数据结构——顺序表单链表oj详解
  • 8.15 机器学习(2)K最近邻算法
  • k8s注意事项
  • Nginx反向代理Tomcat实战指南
  • 8月4日实训考察:重庆五一职院走进成都国际影像产业园
  • PCA降维 提升模型训练效率