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

SQL184 近三个月未完成试卷数为0的用户完成情况

描述

现有试卷作答记录表exam_record(uid:用户ID, exam_id:试卷ID, start_time:开始作答时间, submit_time:交卷时间,为空的话则代表未完成, score:得分):

iduidexam_idstart_timesubmit_timescore
1100690032021-09-06 10:01:012021-09-06 10:21:0284
2100690012021-08-02 12:11:012021-08-02 12:31:0189
3100690022021-06-06 10:01:012021-06-06 10:21:0181
4100690022021-05-06 10:01:012021-05-06 10:21:0181
5100690012021-05-01 12:01:01(NULL)(NULL)
6100190012021-09-05 10:31:012021-09-05 10:51:0181
7100190032021-08-01 09:01:012021-08-01 09:51:1178
8100190022021-07-01 09:01:012021-07-01 09:31:0081
9100190022021-07-01 12:01:012021-07-01 12:31:0181
10100190022021-07-01 12:01:01(NULL)(NULL)

找到每个人近三个月有试卷作答记录的月份中没有试卷是未完成状态的用户的试卷作答完成数,按试卷完成数和用户ID降序排名。由示例数据结果输出如下:

uidexam_complete_cnt
10063


解释:用户1006近三个月有作答试卷的月份为202109、202108、202106,作答试卷数为3,全部完成;用户1001近三个月有作答试卷的月份为202109、202108、202107,作答试卷数为5,完成试卷数为4,因为有未完成试卷,故过滤掉。

-- 第一步:按用户+年月分组,标记该月是否有未完成记录
WITH monthly_stats AS (SELECTuid,DATE_FORMAT(start_time, '%Y-%m') AS month,COUNT(*) AS total_cnt,COUNT(score) AS completed_cnt,-- 该月是否有未完成记录SUM(CASE WHEN submit_time IS NULL THEN 1 ELSE 0 END) AS incomplete_cntFROM exam_recordWHERE start_time IS NOT NULLGROUP BY uid, DATE_FORMAT(start_time, '%Y-%m')
),
-- 第二步:对每个用户的月份排名
ranked_months AS (SELECTuid,month,completed_cnt,DENSE_RANK() OVER (PARTITION BY uid ORDER BY month DESC) AS month_rankFROM monthly_stats
)
-- 第三步:只保留最近3个月,且无任何未完成记录的用户
SELECTuid,SUM(completed_cnt) AS exam_complete_cnt
FROM ranked_months
WHERE month_rank <= 3AND uid NOT IN (-- 排除在最近3个月中有未完成记录的用户SELECT uid FROM monthly_stats WHERE month IN (SELECT month FROM ranked_months WHERE month_rank <= 3)AND incomplete_cnt > 0)
GROUP BY uid
ORDER BY exam_complete_cnt DESC, uid DESC;

🔍 代码逐层解析

🧱 1. WITH monthly_stats —— 按“用户+月份”聚合

SELECTuid,DATE_FORMAT(start_time, '%Y-%m') AS month,COUNT(*) AS total_cnt,                    -- 该月总考试次数COUNT(score) AS completed_cnt,            -- 完成次数(score非空)SUM(CASE WHEN submit_time IS NULL THEN 1 ELSE 0 END) AS incomplete_cnt
FROM exam_record
WHERE start_time IS NOT NULL
GROUP BY uid, DATE_FORMAT(start_time, '%Y-%m')
✅ 做了什么?
  • 将数据从“按记录”提升到“按用户+月份”维度。
  • 每行代表:某个用户在某个月的考试汇总。
📊 示例输出(部分):
uidmonthtotal_cntcompleted_cntincomplete_cnt
10062021-09110
10062021-08110
10062021-06110
10062021-05211
10012021-09110
10012021-08110
10012021-07321

💡 incomplete_cnt > 0 表示该月有未完成考试。


🧱 2. ranked_months —— 对“月份”进行排名

SELECTuid,month,completed_cnt,DENSE_RANK() OVER (PARTITION BY uid ORDER BY month DESC) AS month_rank
FROM monthly_stats
✅ 做了什么?
  • 对每个用户的“活跃月份”按时间倒序排名。
  • 最近的月份排第 1 名,次近排第 2,依此类推。
  • 使用 DENSE_RANK() 而非 ROW_NUMBER(),避免跳过排名。
📊 示例(uid=1001):
uidmonthcompleted_cntmonth_rank
10012021-0911
10012021-0812
10012021-0723

🧱 3. 主查询 —— 筛选 + 聚合

SELECTuid,SUM(completed_cnt) AS exam_complete_cnt
FROM ranked_months
WHERE month_rank <= 3AND uid NOT IN (SELECT uid FROM monthly_stats WHERE month IN (SELECT month FROM ranked_months WHERE month_rank <= 3)AND incomplete_cnt > 0)
GROUP BY uid
ORDER BY exam_complete_cnt DESC, uid DESC;
✅ 逻辑拆解:
条件说明
WHERE month_rank <= 3只保留每个用户最近 3 个活跃月份的数据
uid NOT IN (...)排除那些在“最近3个月”中有任何一个月存在未完成记录的用户
SUM(completed_cnt)对符合条件的用户,累加其在最近3个月的完成次数
GROUP BY uid按用户聚合
ORDER BY ...按完成数降序,用户 ID 降序

📝 核心知识点总结

技术点说明应用场景
DATE_FORMAT(start_time, '%Y-%m')提取年月,用于时间维度聚合按月分析用户行为
GROUP BY uid, month将数据从“记录级”升到“用户+月级”汇总每月指标
COUNT(score)统计非空值数量 → 完成数过滤未完成记录
SUM(CASE WHEN ... THEN 1 ELSE 0 END)标记并统计特定状态(如未完成)状态检测
DENSE_RANK() OVER (ORDER BY month DESC)对时间倒序排名,取最近N期最近N个月分析
WITH ... AS ()CTE 公共表表达式分步处理复杂逻辑
uid NOT IN (子查询)排除满足条件的用户黑名单过滤
http://www.dtcms.com/a/343753.html

相关文章:

  • XP系统安装Android Studio 3.5.3并建立Java或Native C++工程,然后在安卓手机上运行
  • 【渲染流水线】[逐片元阶段]-[混合Blend]以UnityURP为例
  • 螺旋槽曲面方程的数学建模与偏导数求解
  • Unreal Engine UProjectileMovementComponent
  • 如何生成网关路由表
  • clickhouse实战(二)
  • 关于爬虫的基本步骤说明【爬虫七步骤】
  • AI适老服务暖人心:AI适老机顶盒破数字鸿沟、毫米波雷达护独居安全,银发生活新保障
  • 大模型压缩三剑客:量化、剪枝与知识蒸馏全解析
  • Logstash——安全与权限管理
  • Swift 项目结构详解:构建可维护的大型应用
  • 【Feed-forward optimization】 in Visual Geometry Grounded and 3DGS
  • Matrix-Zero:昆仑万维发布的AI世界模型,支持单张图生成3D世界
  • (纯新手教学)计算机视觉(opencv)实战七——边缘检测Sobel 算子(cv2.Sobel())详解
  • ⭐CVPR2025 无约束 3D 视线估计新框架[特殊字符]
  • 【图像算法 - 21】慧眼识虫:基于深度学习与OpenCV的农田害虫智能识别系统
  • Python opencv识别图片中重叠圆的圆心位置
  • 焊接工艺仿真软件SYSWELD、Simufact.Welding和FLOW-3D WELD的区别
  • 【0基础3ds Max】捕捉工具详解
  • 城市生命线地下管网三维建模软件MagicPipe3D更新历史
  • ZBrush和3D-Coat如何实现快速桥接?
  • `git mv` 重命名 Git 仓库中的文件夹
  • OFSP路由与传输层协议
  • LLM实践系列:利用LLM重构数据科学流程
  • 亚矩阵云手机:亚马逊第三方店铺多账号安全合规运营的核心技术支撑
  • 代码随想录Day59:图论(最短路算法dijkstra堆优化版精讲、Bellman_ford 算法精讲)
  • 【生成树+环】题解:P3907 环的异或_图论_环_异或_搜索_算法竞赛_C++
  • 【typenum】 22 类型级别二进制对数运算(Logarithm2)
  • Apache Ozone 介绍与部署使用(最新版2.0.0)
  • Vue2+Vue3前端开发_Day6