一聚教程网:一个值得你收藏的教程网站

热门教程

SQL中如何利用窗口函数如ROW_NUMBER进行基础排序

时间:2026-07-03 10:55:51 编辑:袖梨 来源:一聚教程网

ROW_NUMBER() 必须配合 OVER() 使用,且 OVER() 中必须包含 ORDER BY,PARTITION BY 可选但需在 ORDER BY 前;ORDER BY 应含多字段以确保编号稳定;与 RANK()/DENSE_RANK() 行为不同,不可混用。

ROW_NUMBER() 必须带 OVER(),否则直接报错

单独写 ROW_NUMBER() 会触发语法错误,不是函数调用失败,而是 SQL 解析器根本认不出这个写法。它不是普通函数,是窗口函数,必须绑定 OVER() 子句。

常见错误现象:ERROR: window function ROW_NUMBER requires an OVER clause

  • OVER() 里至少要有 ORDER BY,哪怕你只想要个任意顺序的编号,也得写上(比如 ORDER BY id
  • 如果漏了 ORDER BY,语句直接无法执行,数据库不会“默认按主键排”或“按插入顺序排”
  • PARTITION BY 是可选的,但位置必须在 ORDER BY 前面,顺序不能颠倒

全局排序 vs 分组内排序,就看有没有 PARTITION BY

要不要分组,全靠 PARTITION BY 控制。它不是“加分项”,而是逻辑开关。

  • 想给整张表所有行从 1 开始连续编号 → 只写 OVER (ORDER BY created_at DESC),不加 PARTITION BY
  • 想按用户分组,每个用户内部独立编号 → 必须写 OVER (PARTITION BY user_id ORDER BY order_time DESC)
  • 漏掉 PARTITION BY 却以为实现了“每组 Top 1”,结果取出来的是全表第一条,不是每组第一条

ORDER BY 多字段决定编号是否稳定

ORDER BY 不只是影响谁排前面,更影响编号结果是否可复现。尤其当排序字段有重复值时,单靠一个字段容易出问题。

  • 例如:按 salary DESC 排序,但多人同薪 → 数据库可能每次返回不同 rn
  • 解决办法:加二级排序,比如 ORDER BY salary DESC, emp_id ASC,让排序完全确定
  • 在分布式查询或并行执行环境下,这种不确定性更容易暴露,不是偶发 bug,而是设计缺陷

ROW_NUMBER() 和 RANK()/DENSE_RANK() 别混用

三者都编号,但行为差异直接影响业务结果。用错一个,Top N 或去重就漏数据。

  • ROW_NUMBER():强行唯一,同分也给不同号(1,2,3)
  • RANK():同分同号,跳过后续号(1,1,3)
  • DENSE_RANK():同分同号,不跳号(1,1,2)
  • 典型误用:用 ROW_NUMBER() + WHERE rn = 1 取“所有最高分员工”,结果只拿到一个;该用 RANK() 才对
实际使用时,最容易被忽略的是排序字段的确定性 —— 没加二级排序的 ORDER BY 在生产环境里往往表现不稳定,尤其当数据量大、查询并发高时,同一语句反复执行可能返回不同 rn 值。

热门栏目