RANK()和DENSE_RANK()均需配合OVER(ORDER BY)使用,区别在于并列时RANK()跳号(如1,1,3)、DENSE_RANK()不跳号(如1,1,2),且二者仅可用于SELECT列表,不可出现在WHERE或GROUP BY中。
MySQL 8.0中RANK()和DENSE_RANK()的基本用法区别
MySQL 8.0开始原生支持窗口函数,
和
都能实现分组内排序编号,但处理并列的方式不同:遇到相同值时,
会跳过后续名次(比如 1,1,3),而
不跳过(1,1,2)。这个差异直接影响业务语义——比如“年级前10名”用
可能实际返回12人,“同分同名次且不空号”则必须选
。
两者语法完全一致,都依赖
子句定义排序逻辑:
按部门分组排名时必须加PARTITION BY
如果要查“每个部门内员工薪资排名”,漏写
就会变成全表统一排名,这是新手最常踩的坑。窗口函数不会自动按 GROUP BY 分组,它只认
里的显式声明。
正确写法示例:
表示按部门切片,各组独立计算排名
ORDER BY 必须存在,否则报错
若需先按部门、再按入职时间保序,可写
ORDER BY 中NULL值影响排名结果
MySQL 8.0默认把
当作最小值(等价于
),所以
会让
排在最后;但若字段本身含大量
,且你希望它们排最前或忽略,就得显式控制:
MySQL(Linux)
MySQL 9.6.0是面向Linux平台的2026年创新版本,核心架构迎来重大革新。其将外键约束与级联操作从InnoDB引擎层上移至SQL层,确保所有数据变更均被完整记录至Binlog,彻底解决了CDC(变更数据捕获)与主从复制中的数据不一致难题。此外,该版本引入container_aware启动选项以原生适配容器环境,并对审计日志进行了组件化重构,为追求极致数据一致性与云原生体验的开发者提供了全新选择。
下载
让 NULL 排最前:
让 NULL 排最后(默认行为):
彻底排除 NULL 行:
(推荐在 WHERE 阶段过滤,比在窗口里处理更高效)
不声明
时,不同 MySQL 版本或 SQL 模式下行为可能不一致,线上环境务必显式指定。
性能注意:大表上慎用无索引的ORDER BY字段
窗口函数的
字段如果没有索引,MySQL 会强制触发临时表 + filesort,数据量稍大(比如百万级)就明显变慢。这不是语法问题,而是执行计划层面的瓶颈。
检查执行计划:
,关注
列是否出现
给排序字段建索引:
(MySQL 8.0 支持降序索引)
避免在
中用函数或表达式,如
会导致索引失效
真正容易被忽略的是:即使加了索引,如果
和
字段组合无法命中联合索引前缀,照样会回退到临时表。这时候得按分区键+排序键建联合索引。
RANK()DENSE_RANK()RANK()DENSE_RANK()RANK()DENSE_RANK()OVER()SELECT name, score,
RANK() OVER (ORDER BY score DESC) AS rank_num,
DENSE_RANK() OVER (ORDER BY score DESC) AS dense_num
FROM students;PARTITION BY deptOVER()SELECT dept, name, salary,
RANK() OVER (PARTITION BY dept ORDER BY salary DESC) AS dept_rank
FROM employees;PARTITION BY deptWindow 'w' lacks an ORDER BY clauseORDER BY salary DESC, hire_date ASCNULLNULLS FIRSTORDER BY score DESCNULLNULLORDER BY score DESC NULLS FIRSTORDER BY score DESC NULLS LASTWHERE score IS NOT NULLNULLS FIRST/LASTORDER BYEXPLAIN SELECT ... RANK() OVER (ORDER BY unindexed_col) ...ExtraUsing temporary; Using filesortALTER TABLE students ADD INDEX idx_score_desc (score DESC);ORDER BYORDER BY ABS(score)PARTITION BYORDER BY