首页 > 数据库 >SQL面试必考窗口函数实战 ROW_NUMBER与RANK的区别分析

SQL面试必考窗口函数实战 ROW_NUMBER与RANK的区别分析

来源:互联网 2026-04-19 19:58:05

ROW_NUMBER() 与 RANK():一字之差,逻辑天壤之别 ROW_NUMBER() 和 RANK() 的结果差异,根本在于排序逻辑 许多开发者虽然语法熟练,但实际结果却与预期不符。问题的根源并非代码错误,而是两者在处理重复值时存在根本性的逻辑差异——这是设计使然,而非程序漏洞。 ROW_N

ROW_NUMBER() 与 RANK():一字之差,逻辑天壤之别

SQL面试必考窗口函数实战 ROW_NUMBER与RANK的区别分析

ROW_NUMBER() 和 RANK() 的结果差异,根本在于排序逻辑

许多开发者虽然语法熟练,但实际结果却与预期不符。问题的根源并非代码错误,而是两者在处理重复值时存在根本性的逻辑差异——这是设计使然,而非程序漏洞。

长期稳定更新的攒劲资源: >>>点此立即查看<<<

  • ROW_NUMBER() 严格按行赋予唯一序号,不考虑值是否相同。即使两行的salary字段值都是25000,它也会依次分配1和2。
  • RANK() 则遵循现实世界的排名规则:数值相同则名次并列,后续名次会跳过被占用的序号。例如,两个第一名之后,下一个名次直接就是第三名。
  • 通过一个例子可以清晰对比:对数据[90, 85, 85, 80]执行SELECT score, ROW_NUMBER() OVER (ORDER BY score DESC), RANK() OVER (ORDER BY score DESC),输出结果分别为[1,2,3,4][1,2,2,4]

如何选择?取决于你需要“序号”还是“名次”

这并非个人风格偏好,而是关系到业务逻辑的准确性。选择错误可能导致整个分析方向偏离。

  • 需要获取每个部门最新的一条订单记录?应使用ROW_NUMBER() OVER (PARTITION BY dept_id ORDER BY create_time DESC),然后通过WHERE rn = 1过滤。此场景要求序号绝对唯一,不允许并列。
  • 制作销售业绩排行榜,且允许存在并列名次?则应使用RANK() OVER (ORDER BY amount DESC),再配合WHERE rk <= 3。这样,如果两人并列第一,一人第三,你就能正确获取三条记录。
  • 若误用ROW_NUMBER()来实现“取前三名”,实际上只会得到三条记录,并列者将被遗漏——这是面试和线上事故中的常见错误。

常见误区:别名无法在 WHERE 中直接使用,PARTITION BY 错误将导致结果混乱

窗口函数在SELECT阶段进行计算,而WHERE子句的执行顺序在其之前。因此,在同一查询层级中,WHERE无法直接引用窗口函数生成的别名。此外,分组维度一旦设置错误,排名结果将完全失真。

  • 错误示例:SELECT *, RANK() OVER (ORDER BY score) AS rk FROM scores WHERE rk <= 10 —— 这将导致报错或逻辑错误。
  • 正确做法:必须使用子查询或CTE进行嵌套,在外部进行过滤:SELECT * FROM (SELECT *, RANK() OVER (...) AS rk FROM scores) t WHERE t.rk <= 10
  • 如果将PARTITION BY dept_id误写为PARTITION BY city,结果会变成“每个城市的员工在部门内排名”这种逻辑混乱的局面。因此,上线前仔细核对业务口径与字段含义,往往比反复调试SQL更为重要。

MySQL 8.0+ 性能建议:无特殊需求时,优先选用 ROW_NUMBER()

在千万级数据量的实际测试中,ROW_NUMBER()的性能通常比RANK()稳定高出10%至15%。原因在于,RANK()需要额外扫描重复数据块以确定跳号位置,计算开销更大。

  • 如果业务场景仅涉及分页、去重、或获取Top N(且无需处理并列情况),那么ROW_NUMBER()是更轻量、更安全的选择。
  • RANK()DENSE_RANK()在高并发的OLAP场景下,可能因其内部的排序缓存策略导致性能波动,建议上线前进行压力测试对比。
  • 需要特别注意,这三个窗口函数均要求MySQL版本在8.0及以上。低版本虽可通过变量模拟,但变量方案在多线程或并行查询环境下极易出错,风险较高。

归根结底,真正的难点往往不在于OVER子句的写法,而在于想清楚一个根本问题:你需要的究竟是“第几个被读取的行”的序号,还是“第几名”的真实排名。

侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述

热游推荐

更多
湘ICP备14008430号-1 湘公网安备 43070302000280号
All Rights Reserved
本站为非盈利网站,不接受任何广告。本站所有软件,都由网友
上传,如有侵犯你的版权,请发邮件给xiayx666@163.com
抵制不良色情、反动、暴力游戏。注意自我保护,谨防受骗上当。
适度游戏益脑,沉迷游戏伤身。合理安排时间,享受健康生活。