窗口函数

news/2025/11/2 19:05:51/文章来源:https://www.cnblogs.com/clarencezzh/p/19185284
窗口函数:它们都用于为查询结果集中的每一行分配一个排名或序号

核心区别总结表

函数功能描述排序特点(针对相同值)序号示例
ROW_NUMBER() 为每一行生成一个唯一的、连续的序号。 即使值相同,也会分配不同序号(顺序不确定)。 1, 2, 3, 4, ...
RANK() 为每一行生成一个排名,允许并列 相同值的行排名相同,但下一个不同值的排名会跳过并列占用的序号 1, 2, 2, 4, ...
DENSE_RANK() 为每一行生成一个排名,允许并列 相同值的行排名相同,但下一个不同值的排名连续,不跳过序号 1, 2, 2, 3, ...

详细解释和示例

假设我们有一张学生成绩表 scores
student_namescore
张三 95
李四 92
王五 92
赵六 88
孙七 85
现在我们使用这三个函数,按分数 score降序排列。 SQL 查询语句:
SELECTstudent_name,score,ROW_NUMBER() OVER (ORDER BY score DESC) AS rn,RANK() OVER (ORDER BY score DESC) AS rk,DENSE_RANK() OVER (ORDER BY score DESC) AS dr
FROM scores;
查询结果:
student_namescorern (ROW_NUMBER)rk (RANK)dr (DENSE_RANK)
张三 95 1 1 1
李四 92 2 2 2
王五 92 3 2 2
赵六 88 4 4 3
孙七 85 5 5 4

逐行分析结果

  1. 第一行(张三,95分)
    • 三个函数都从 1 开始,所以结果都是 1
  2. 第二行和第三行(李四和王五,都是92分)
    • ROW_NUMBER():必须生成唯一序号,所以即使分数相同,它也强制分配了 23。至于谁得2谁得3,在没有其他排序条件的情况下是不确定的
    • RANK():遇到相同分数(92分),它赋予它们相同的排名 2
    • DENSE_RANK():同样赋予它们相同的排名 2
  3. 第四行(赵六,88分):这是关键区别所在!
    • ROW_NUMBER():继续连续编号,所以是 4
    • RANK():之前有两个并列第2名,它们占用了排名2和3。所以下一个排名(赵六的排名)应该从 4开始。这就是 “跳过”的含义。
    • DENSE_RANK():它不关心有多少个并列。上一个有效的排名是 2,所以下一个排名就是 3。序号是 “密集的”,连续不间断。
  4. 第五行(孙七,85分)
    • ROW_NUMBER():编号为 5
    • RANK():由于没有新的并列,它继续编号为 5
    • DENSE_RANK():继续编号为 4

什么时候用?

  • ROW_NUMBER()
    • 需要绝对唯一序号时。例如,给用户列表编号,或者进行分页查询(如每页10条,用 rn BETWEEN 11 AND 20来取第二页)。
    • 需要从每组中选取Top N记录时(通常与 PARTITION BY联用)。
  • RANK()
    • 标准的排名,符合大多数体育比赛或竞赛的规则。比如奥运会奖牌榜,如果有两个金牌,下一个就是铜牌(排名第3)。
  • DENSE_RANK()
    • 当你关心“价值”的等级而不是位置时。比如,想知道95分是第1等,92分是第2等,88分是第3等,而不在乎中间有多少人并列。

关键语法点回顾

所有这些函数都必须与 OVER()子句一起使用。OVER()中的 ORDER BY决定了排名的依据
FUNCTION_NAME() OVER (ORDER BY column_name [ASC|DESC])

PARTITION BY 详解

PARTITION BY用于在窗口函数中进行分组计算,类似于 GROUP BY的概念,但关键区别是:它不会合并行,而是在每个分组内独立进行计算

基本语法

函数名() OVER (PARTITION BY 分组字段 ORDER BY 排序字段
)

具体示例

假设我们有一个更详细的学生成绩表:
student_idstudent_nameclass_namescore
1 张三 一班 95
2 李四 一班 92
3 王五 一班 88
4 赵六 二班 96
5 孙七 二班 90
6 周八 二班 90
7 吴九 二班 85

查询语句:计算每个班级内部的排名

SELECTstudent_id,student_name,class_name,score,ROW_NUMBER() OVER (PARTITION BY class_name ORDER BY score DESC) AS rn,RANK() OVER (PARTITION BY class_name ORDER BY score DESC) AS rk,DENSE_RANK() OVER (PARTITION BY class_name ORDER BY score DESC) AS dr
FROM students;

查询结果:

student_idstudent_nameclass_namescorernrkdr
1 张三 一班 95 1 1 1
2 李四 一班 92 2 2 2
3 王五 一班 88 3 3 3
4 赵六 二班 96 1 1 1
5 孙七 二班 90 2 2 2
6 周八 二班 90 3 2 2
7 吴九 二班 85 4 4 3

结果分析

一班的情况:

  • 张三:95分,班级第1名(rn=1, rk=1, dr=1)
  • 李四:92分,班级第2名(rn=2, rk=2, dr=2)
  • 王五:88分,班级第3名(rn=3, rk=3, dr=3)

二班的情况(注意排名重置):

  • 赵六:96分,在二班内重新从第1名开始排名(rn=1, rk=1, dr=1)
  • 孙七周八:都是90分,出现并列
    • ROW_NUMBER():强制分配2和3(不确定顺序)
    • RANK():都排名第2,下一个吴九排名第4(跳过第3名)
    • DENSE_RANK():都排名第2,下一个吴九排名第3(连续)

PARTITION BY 的更多实用例子

1. 查询每个班级的前2名学生

SELECT * FROM (SELECTstudent_name,class_name,score,ROW_NUMBER() OVER (PARTITION BY class_name ORDER BY score DESC) as rank_in_classFROM students
) AS ranked_students
WHERE rank_in_class <= 2;

2. 计算每个学生的成绩在班级内的百分比排名

SELECTstudent_name,class_name,score,ROUND(PERCENT_RANK() OVER (PARTITION BY class_name ORDER BY score) * 100, 2) as percentile_in_class
FROM students;

3. 与其他窗口函数结合使用

SELECTstudent_name,class_name,score,-- 班级内排名RANK() OVER (PARTITION BY class_name ORDER BY score DESC) as class_rank,-- 班级内平均分AVG(score) OVER (PARTITION BY class_name) as class_avg,-- 班级内最高分MAX(score) OVER (PARTITION BY class_name) as class_max
FROM students;

PARTITION BY 的核心优势

  1. 分组不合并:在每个分组内独立计算,但保持所有原始数据行
  2. 排名重置:每个分组的排名都从1重新开始
  3. 灵活组合:可以按多个字段分区:PARTITION BY class_name, subject_name
  4. 性能优化:比使用多个子查询或自连接更高效
PARTITION BY它实现了"既要分组计算,又要保留明细数据"的需求。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/953743.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

别只怪客户端宕机!还有这些导致 Redis 分布式锁“死锁”的原因 - 公众号

本文已收录在Github,关注我,紧跟本系列专栏文章,咱们下篇再续!🚀 魔都架构师 | 全网30W技术追随者🔧 大厂分布式系统/数据中台实战专家🏆 主导交易系统百万级流量调优 & 车联网平台架构🧠 AIGC应用开发…

CCF CSP-S2 2025 游记

\(\text{Day0}\) 看到了 2024 年的第三题,我一直在复习组合计数 DP。结果,一天就弄懂了两道题。。。 \(\text{Day1}\) 第一件事自然是洛谷签到,中吉,忌出行、摸鱼。 早上八点出发,一早起来大雾,告诉走不了高速,…

CSP-S 2025 总结

114,514,1919810.0.前言 信心十足! 1.正文 不会做原题。 2.总结 我是人类吗?

LangChain v1.0 中间件详解:彻底搞定 AI Agent 上下文控制

用 LangChain 构建 AI Agent 的人应该都遇到过这种情况:测试阶段一切正常,部署到生产环境就开始出各种问题。上下文管理混乱,Agent 的行为变得难以预测,最后不得不写一堆自定义代码来控制信息流向。 这是因为在v1.…

【EF Core】“多对多”关系与跳跃导航

“多对多”关系不像“一对多”那么“单纯”,它内部涉及到“连接实体”(Join Entity)的概念。咱们先放下这个概念不表,来了解一下多对多数据表为什么需要一个“辅助表”来建立关系。 假设有两张表:一张表示学生,一…

DeepSeek-MTP多token预测

多Token预测(Multi-Token Prediction, MTP)是DeepSeek-V3模型的一项核心创新技术,旨在通过一次前向传播预测多个未来词元,从而显著提升模型的训练效率和推理速度,同时增强对上下文的理解能力。该技术原始论文是由…

11.2阅读笔记

《断言式编程》这一章教我如何主动地、有章法地处理程序中的“意外”情况。 ​​1. 断言式编程:明确你的假设​​ “断言式编程”的核心思想是:​​用代码明确地表达你对程序状态的假设,如果假设被违反,就果断地报…

温故知新,英语口语提升计划之Social English - Greeting People

Greeting People Look at some ways to greet people. Do you greet people that you meet for the first time the same way that you greet people you know? What can change? Greeting People You Meet for the …

23432

23432 32423 ‍本文来自博客园,作者:对象存储与RustFS,转载请注明原文链接:https://www.cnblogs.com/rsfs/p/19185241/23432-2fnvqw

关于dp

dddddddddpppppppp发扬多头精神,质疑dp,理解dp,成为dp! 由浅入深 ATcoder Dp 普及~提高的版子记录 LinkA - Frog 1B - Frog 2C - VacationD - Knapsack 1E - Knapsack 2F - LCSG - Longest PathH - Grid 1I - Coin…

Git 协作实战与 Gerrit 评审流程

Git 协作实战与 Gerrit 评审流程Git 协作实战与 Gerrit 评审流程适用场景:公司内网仓库 + Gerrit 评审流程;服务器上 Git 版本较老(无 git switch、git restore)。 示例仓库:/home/aaa/bbb/ccc,远端别名 origin。…

分库分表MyCat 架构迁移 OceanBase | 百丽核心财务系统迁移经验总结与问题汇总

分库分表MyCat 架构迁移 OceanBase | 百丽核心财务系统迁移经验总结与问题汇总百丽时尚集团(以下简称百丽)是中国领先的大型时尚鞋服集团,其核心财务系统刚刚经历了一场“换心脏”手术。 本文详细拆解MyCat 切换 Oc…

算法研究内容算法有关概念

1.1调度问题与投资问题 1. 调度问题问题&建模2. 贪心算法: 加工时间短的先做,加工时间从小到大排序(有反例 根据实际问题使用) 3. 算法设计: 1.问题建模 2.选择什么算法?如何描述这个算法? 3.这个算法是否对所有…

第13天(中等题 滑动窗口)

打卡第十三天 2道中等题一个高效的方法来获取数组中所有不重复的元素。 unordered_set<int> uniqueSet(nums.begin(), nums.end());//获取数组中所有不重复的数字 int k = uniqueSet.size();//不重复数字的个数k…

我重生了,重生到了CSP前——高中物理电学速通

喜报:CSP炸了,然后两天之后学校期中考,我夺回属于我的所有!(?) 电荷和元电荷有新的旅行伙伴加入了: $ \ \ \ \ $ 电荷量(符号 \(\mathit{Q}\) 单位 \(\mathit{C}\) )电量荷是有基本单位的,也就是一个电子所带的电…

列车驶向何处 | CSP-S 2025 #3

整个十月的下半是在来来往往的列车上度过的。从苏州往返上海,北京,南京,每一次的结果好像都并不如意。 这个月第一次踏上列车是上海的数学基础测试,机试,十五道题,只填正整数。进场前的目标是十二个题,后来变成…

为啥slmbuild的cutoff不能设得很大

为啥slmbuild的cutoff不能设得很大在sim_slmbuilder.cpp的CSlmBuilder::AddNGram里:if (fr > cut[nlevel]) {TLeafLevel& v = *(TLeafLevel*)(level[nlevel]);v.push_back(TLeaf(ngram[nlevel - 1], fr)); } e…

团队项目1-团队展示选题-图书管理系统

项目信息-图书管理系统项目 内容所属课程 https://edu.cnblogs.com/campus/gdgy/Class12Grade23ComputerScience作业要求 https://edu.cnblogs.com/campus/gdgy/Class12Grade23ComputerScience/homework/13471作业目标…

第二天,学习部分快捷键位(重点加粗)

快捷键位复制 ctrl+C 粘贴 ctrl+V 全选 ctrl+A 剪切 ctrl+X 撤销 ctrl+Z 保存 ctrl+S 关闭 alt+F4 永久删除 shift+delete 打开命令窗口 win+R 打开任务管理器 ctrl+shift+Esc 切换屏幕 win+Tap