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

SQL180 每类试卷得分前3名

描述

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

idexam_idtagdifficultydurationrelease_time
19001SQLhard602021-09-01 06:00:00
29002SQLhard602021-09-01 06:00:00
39003算法medium802021-09-01 10:00:00


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

iduidexam_idstart_timesubmit_timescore
1100190012021-09-01 09:01:012021-09-01 09:31:0078
2100190012021-09-01 09:01:012021-09-01 09:31:0081
3100290022021-09-01 12:01:012021-09-01 12:31:0181
4100390012021-09-01 19:01:012021-09-01 19:40:0186
5100390022021-09-01 12:01:012021-09-01 12:31:5189
6100490012021-09-01 19:01:012021-09-01 19:30:0185
7100590032021-09-01 12:01:012021-09-01 12:31:0285
8100690032021-09-07 10:01:012021-09-07 10:21:0184
9100390032021-09-08 12:01:012021-09-08 12:11:0140
10100390022021-09-01 14:01:01(NULL)(NULL)

找到每类试卷得分的前3名,如果两人最大分数相同,选择最小分数大者,如果还相同,选择uid大者。由示例数据结果输出如下:

tag

uidranking
SQL10031
SQL10042
SQL10023
算法10051
算法10062
算法10033


解释:有作答得分记录的试卷tag有SQL和算法,SQL试卷用户1001、1002、1003、1004有作答得分,最高得分分别为81、81、89、85,最低得分分别为78、81、86、40,因此先按最高得分排名再按最低得分排名取前三为1003、1004、1002。

SELECTtag,uid,ranking
FROM(SELECTei.tag,er.uid,MAX(er.score) AS max_score, -- 每个用户在该类别下的最高分MIN(er.score) AS min_score, -- 最低分(用于平局决胜)ROW_NUMBER() OVER (PARTITION BYei.tagORDER BYMAX(er.score) DESC, -- 先按最高分排序MIN(er.score) DESC, -- 再按最低分排序er.uid DESC -- 最后按 uid 排序) AS rankingFROMexamination_info eiJOIN exam_record er USING (exam_id)WHEREer.score IS NOT NULL -- 只统计有得分的记录GROUP BYei.tag,er.uid -- 按“类别+用户”分组) t
WHEREranking <= 3 -- 取前3名
ORDER BYtag,ranking;

窗口函数

1. 窗口函数基本格式

函数名() OVER (PARTITION BY 分组字段   -- 按什么分组(可选)ORDER BY 排序字段       -- 按什么排序(必选)
) 

👉 就像“分组 + 排序 + 计算”,但不改变行数


2. 常用函数

函数作用
ROW_NUMBER()排名:1,2,3,4…(不并列)
RANK()排名:1,2,2,4…(并列,跳号)
DENSE_RANK()排名:1,2,2,3…(并列,不跳号)

3. 举个例子

ROW_NUMBER() OVER (PARTITION BY class ORDER BY score DESC
)

意思:

  • 每个班(class)单独排名
  • 按分数从高到低排
  • 返回排名:第1名、第2名…

4. 注意!

  • 窗口函数不能直接在 WHERE 里用
  • 要用的话,得套一层子查询
SELECT * FROM (SELECT ..., ROW_NUMBER() OVER (...) AS rnFROM table
) t
WHERE rn <= 3;  -- ✅ 这样才能用

✅ 一句话记住

PARTITION BY 分组,ORDER BY 排序,ROW_NUMBER() 给每行打上排名。


http://www.dtcms.com/a/328528.html

相关文章:

  • Mybatis源码解读-Plugin插件源码
  • (C++)继承全解析及运用
  • Labelme从安装到标注:零基础完整指南
  • MySQL基础面试
  • Springboot整合Thrift
  • 移动端网页调试实战,键盘弹出与视口错位问题的定位与优化
  • 汉高携手SAP推出AI驱动的退换货与争议管理解决方案
  • 赛灵思ZYNQ官方文档UG585自学翻译笔记:UART Controller,通用异步收发传输器控制器
  • Vue接口平台十三——测试记录
  • Ubuntu 全盘备份
  • 九尾狐未来机械晶核技术
  • k3s部署
  • 电脑硬件详解
  • ZYNQ AXI-GPIO学习——ZYNQ学习笔记8
  • 学习游制作记录(背包UI以及各种物品的存储)8.12
  • kafka 消费者组的概念是什么?它是如何实现消息的点对点和发布/订阅模式?
  • Supabase快速入门与实战指南
  • LangChain 入门学习
  • Spring AI Alibaba - 聊天机器人快速上手
  • SpringAI 使用通义千问进行聊天对话开发
  • 考研复习-计算机组成原理-第五章-CPU
  • [NoC]Outstanding和Credit的概念详解
  • Fluent Bit 日志合并正则表达式(上)
  • Nginx 高级配置
  • Python训练Day41
  • 基于PAI-ChatLearn的GSPO强化学习实践
  • LLM - 搭建 Grounded SAM 2 模型的视觉检测与分割服务 API
  • CMake笔记:PUBLIC/PRIVATE/INTERFACE的使用
  • FreeRTOS---基础知识6---事件组
  • Effective C++ 条款37:绝不重新定义继承而来的缺省参数值