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

SQL185 试卷完成数同比2020年的增长率及排名变化

描述

现有试卷信息表examination_info(exam_id试卷ID, tag试卷类别, difficulty试卷难度, duration考试时长, release_time发布时间):

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

请计算2021年上半年各类试卷的做完次数相比2020年上半年同期的增长率(百分比格式,保留1位小数),以及做完次数排名变化,按增长率和21年排名降序输出。

由示例数据结果输出如下:

解释:2020年上半年有3个tag有作答完成的记录,分别是C++、SQL、PYTHON,它们被做完的次数分别是3、3、2,做完次数排名为1、1(并列)、3;

2021年上半年有2个tag有作答完成的记录,分别是算法、SQL,它们被做完的次数分别是3、2,做完次数排名为1、2;具体如下:

因此能输出同比结果的tag只有SQL,从2020到2021年,做完次数3=>2,减少33.3%(保留1位小数);排名1=>2,后退1名。

WITHt2 AS (SELECTexam_id,IF(start_year = '2020', exam_cnt, NULL) exam_cnt_20, -- 2020年的完成次数LEAD(exam_cnt, 1) OVER (PARTITION BYexam_idORDER BYstart_year) exam_cnt_21, -- 2021年的完成次数IF(start_year = '2020', rk, NULL) exam_cnt_rank_20, -- 2020年的排名LEAD(rk, 1) OVER (PARTITION BYexam_idORDER BYstart_year) exam_cnt_rank_21 -- 2021年的排名FROM(SELECTexam_id,YEAR(submit_time) start_year,COUNT(score) exam_cnt,RANK() OVER (PARTITION BYYEAR(submit_time)ORDER BYCOUNT(score) DESC) rk/*分别对2021和2020的做完情况进行排名*/FROMexam_recordWHEREMONTH(submit_time) BETWEEN 1 AND 6 -- 选取上半年数据AND submit_time BETWEEN '2020-01-00 00:00:00' AND '2022-01-01 00:00:00' -- 选取2020和2021年的数据GROUP BYYEAR(submit_time),exam_id/*对年份和类别进行聚类*/) t1)
SELECTa.tag,exam_cnt_20,exam_cnt_21,CONCAT(ROUND((exam_cnt_21 - exam_cnt_20) * 100 / exam_cnt_20,1),'%') AS growth_rate,exam_cnt_rank_20,exam_cnt_rank_21,CAST(exam_cnt_rank_21 AS SIGNED) - CAST(exam_cnt_rank_20 AS SIGNED) AS rank_delta -- 需要转换格式,否则会报错
FROMt2LEFT JOIN examination_info AS a ON a.exam_id = t2.exam_id
WHEREexam_cnt_21 IS NOT NULL
ORDER BYgrowth_rate DESC,exam_cnt_rank_21 DESC;

🔍 代码逐层解析

🧱 1. 内层查询 t1 —— 按年份+试卷分组并排名

SELECTexam_id,YEAR(submit_time) AS start_year,COUNT(score) AS exam_cnt,RANK() OVER (PARTITION BY YEAR(submit_time)ORDER BY COUNT(score) DESC) AS rk
FROM exam_record
WHEREMONTH(submit_time) BETWEEN 1 AND 6AND submit_time >= '2020-01-01' AND submit_time < '2022-01-01'
GROUP BY YEAR(submit_time), exam_id
✅ 做了什么?
  • 筛选 2020 和 2021 年上半年 的数据
  • 按 年份 + 试卷 ID 分组
  • 统计每类试卷每年的完成次数COUNT(score)
  • 使用 RANK() 计算每年内的完成次数排名(降序)
⚠️ 注意:
  • BETWEEN 1 AND 6:精确筛选上半年
  • submit_time < '2022-01-01':避免包含 2022 年数据
  • RANK() 处理并列情况(如 3,3 → 排名 1,1,下一名为 3)

🧱 2. 中层查询 t2 —— 使用 LEAD() 对齐两年数据

SELECTexam_id,IF(start_year = '2020', exam_cnt, NULL) AS exam_cnt_20,LEAD(exam_cnt, 1) OVER (PARTITION BY exam_id ORDER BY start_year) AS exam_cnt_21,IF(start_year = '2020', rk, NULL) AS exam_cnt_rank_20,LEAD(rk, 1) OVER (PARTITION BY exam_id ORDER BY start_year) AS exam_cnt_rank_21
FROM t1
✅ 核心技巧:LEAD() 窗口函数
函数作用
LEAD(col, 1)获取当前行之后第 1 行的值
PARTITION BY exam_id按试卷分组,确保只在同 exam_id 内查找
ORDER BY start_year按年份升序排列(2020 → 2021)
💡 举个例子:

原始 t1 数据:

exam_idstart_yearexam_cntrk
900120201002
900120211501

经过 LEAD() 后:

exam_idexam_cnt_20exam_cnt_21rk_20rk_21
900110015021

✅ 实现了“将两年数据对齐到同一行”

📌 IF(start_year = '2020', ..., NULL) 的作用:
  • 将 2020 年的数据保留在 exam_cnt_20 字段
  • 2021 年该字段为 NULL
  • 配合 LEAD(),确保 exam_cnt_21 是下一年的值

🧱 3. 主查询 —— 计算增长率与排名变化

SELECTa.tag,exam_cnt_20,exam_cnt_21,CONCAT(ROUND((exam_cnt_21 - exam_cnt_20) * 100.0 / exam_cnt_20, 1), '%') AS growth_rate,exam_cnt_rank_20,exam_cnt_rank_21,CAST(exam_cnt_rank_21 AS SIGNED) - CAST(exam_cnt_rank_20 AS SIGNED) AS rank_delta
FROM t2
LEFT JOIN examination_info AS a ON a.exam_id = t2.exam_id
WHERE exam_cnt_21 IS NOT NULL
ORDER BY growth_rate DESC, exam_cnt_rank_21 DESC;
✅ 关键计算:
指标公式说明
增长率(2021 - 2020) / 2020 * 100%* 100.0 保证浮点运算
格式化输出CONCAT(..., '%')添加百分号
排名变化rank_21 - rank_20正数表示排名下降,负数表示上升
类型转换CAST(... AS SIGNED)避免字符串减法报错
✅ 过滤与排序:
  • WHERE exam_cnt_21 IS NOT NULL:确保该试卷在 2020 和 2021 都存在
  • ORDER BY growth_rate DESC:增长率从高到低
  • exam_cnt_rank_21 DESC:2021 年排名靠后的优先(同增长率时)

📝 核心知识点总结

技术点说明应用场景
LEAD()/LAG()获取下一行/上一行的值同比、环比分析
RANK()处理并列排名排行榜、绩效排名
PARTITION BY窗口函数分组分组内排序、对比
CONCAT + ROUND格式化数值输出百分比、金额显示
CAST(... AS SIGNED)类型转换字符串转整数计算
WITH ... AS ()CTE 公共表表达式分步处理复杂逻辑

✅ 最佳实践建议

  1. 时间范围写法

    • ❌ BETWEEN '2020-01-00'(非法日期)
    • ✅ submit_time >= '2020-01-01' AND submit_time < '2022-01-01'
  2. 增长率计算注意除零

    • 可加 WHERE exam_cnt_20 > 0
  3. 排名函数选择

    • RANK():允许并列,下一名跳过(1,1,3)
    • DENSE_RANK():允许并列,下一名不跳过(1,1,2)
    • ROW_NUMBER():强制唯一,无并列
  4. LEAD() 的适用场景

    • 跨行对比(如:今年 vs 去年)
    • 避免自连接,提升性能

🎯 一句话总结

“用 LEAD() 实现跨年数据对齐,RANK() 计算年度排名,CONCAT+ROUND 格式化增长率,完成试卷类别的同比分析”

这套模式适用于:

  • 年度/季度/月度对比分析
  • 排名变化监控
  • 增长率计算与展示
http://www.dtcms.com/a/343757.html

相关文章:

  • C# 简单工厂模式:构建灵活与可扩展的面向对象程序
  • 【实时Linux实战系列】实时气象数据分析系统
  • 【LeetCode题解】LeetCode 287. 寻找重复数
  • SQL184 近三个月未完成试卷数为0的用户完成情况
  • 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 算法精讲)