为什么SQL中的RANK与DENSE_RANK排序结果不同

大瑶小哥_5696

大瑶小哥_5696

2026-09-15

560人浏览

原创

rank() 返回1,1,3,4而dense_rank()返回1,1,2,3,因rank()按相等值分段跳名次(100,100占第1段,下段从3起),dense_rank()按不同值序号连续编号(100、95、90对应1、2、3)。

为什么sql中的rank与dense_rank排序结果不同

为什么 RANK() 返回 1,1,3,4 而 DENSE_RANK() 返回 1,1,2,3

RANK() 把相同排序值看作一个“段”,段内所有行共享名次,下一段名次 = 当前段名次 + 当前段行数;DENSE_RANK() 只关心“这是第几个不同值”,值一变就 +1。

比如分数 [100, 100, 95, 90] 降序排列:

  • RANK():两个 100 占第 1 段(长度 2),所以第 3 行从名次 3 开始 → [1, 1, 3, 4]
  • DENSE_RANK():100 是第 1 个不同值,95 是第 2 个,90 是第 3 个 → [1, 1, 2, 3]

这不是计算错误,是语义设计差异:RANK() 强调“断层感”,DENSE_RANK() 强调“档位连续”。

WHERE 中直接用 RANK() 或 DENSE_RANK() 一定报错

窗口函数在 SELECT 阶段才执行,而 WHERE 在它之前就已过滤完毕。以下写法必然失败:

SELECT * FROM sales WHERE RANK() OVER (ORDER BY amount DESC) <p>报错信息通常是 <code>Invalid use of window function</code> 或字段不存在。</p><p>正确做法必须套一层子查询或 CTE:</p><div class="aritcle_card flexRow artxards">
											<div class="artcardd flexRow">
												<a class="aritcle_card_img" rel="nofollow" href="/ai/1276" title="ARTi.PiCS"><img
														src="https://img.php.cn/upload/ai_manual/001/431/639/68b6da3366e28583.jpeg" alt="ARTi.PiCS" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
												<div class="aritcle_card_info flexColumn">
													<a rel="nofollow" href="/ai/1276" title="ARTi.PiCS" class="overflowclass">ARTi.PiCS</a>
													<p class="overflowclass">ARTi.PiCS是一款用于生成 AI 头像和风格化个人照片的在线工具。</p>
												</div>
												<a rel="nofollow" href="/ai/1276" title="ARTi.PiCS" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
												</a>
											</div>
										</div><pre class="brush:php;toolbar:false;">SELECT * FROM (
  SELECT *, RANK() OVER (ORDER BY amount DESC) AS rnk
  FROM sales
) t WHERE rnk <p>漏掉这层嵌套是新手最高频的坑,和选哪个函数无关,但一旦出错,容易误判为函数本身不可用。</p><h3>PARTITION BY 写错会导致分组排名完全跑偏</h3><p>想按部门排销售榜,却漏写 <code>PARTITION BY dept</code>,结果变成全公司统一排序,不是每部门独立算 Top 3。</p><p>还有几个关键细节容易被忽略:</p>
  • PARTITION BY 字段必须出现在子查询的 SELECT 列表中,否则外部无法对齐分组(多数数据库会报错或静默忽略)
  • 如果排序字段含重复值(如多人同分),不加兜底字段(如 idcreated_at)会导致排名不稳定
  • 安全写法是:ORDER BY score DESC, id ASC;错误写法是仅写 ORDER BY score DESC

选 RANK() 还是 DENSE_RANK() 取决于业务是否允许“空档”

函数选错不会报错,但业务逻辑会悄悄歪掉:

  • RANK() 查 “Top 10” 可能只返回 7 行:因为名次不连续(如只有 1,1,3,4,6…),凑不满 10 个不同名次
  • DENSE_RANK() 做 “前 2 档” 可能返回 15 行:只要档位 ≤ 2,不管每档多少人
  • 报表写 “A档(第1名)、B档(第2名)、C档(第3名)”,DENSE_RANK() 输出天然匹配;RANK()1,1,3 容易引发业务方追问:“第2名去哪了?”

真正容易被忽略的点是:跳不跳号本身不改变性能或语法兼容性,但它直接决定你写的 WHERE dense_rank 是不是真能代表“前 N 档”——而这个判断,只能靠业务语义,不能靠直觉。

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

2023.10.12

3703

8

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.27

771

4

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

2024.02.23

949

5

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

5461

10

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

2463

4

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

2024.04.07

5460

11

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

2024.04.29

7081

6

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

950

5

sql中删除一列的命令是什么
sql中删除一列的命令是什么

在sql中,使用alter table语句可以删除一列,语法为:alter table table_name drop column column_name。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

852

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.6万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 133.1万人学习