最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
为何在SQL中使用DENSE_RANK()比RANK()更符合业务排名逻辑?
时间:2026-07-03 10:56:51 编辑:袖梨 来源:一聚教程网
DENSE_RANK()更符合多数业务排名逻辑,因其并列不跳号,名次连续(如1,1,2,3),直接对应“第几档”业务语义;RANK()并列后跳号(如1,1,3,4),查Top N可能漏数据。
DENSE_RANK() 更符合多数业务排名逻辑,是因为它不跳号 —— 排名数字连续、可预期,直接对应“第几档”或“第几级”的业务语义。
查“Top 3”时,RANK() 可能漏数据
比如销售额为 [100, 100, 90, 85, 80],RANK() 结果是 [1, 1, 3, 4, 5]。用 WHERE rank 只能拿到前三行(两个 100 和一个 90),看似没问题;但若数据变成 <code>[100, 100, 95, 95, 80],RANK() 就是 [1, 1, 3, 3, 5],rank 会返回前四行(两个 100 + 两个 95),而 <code>rank = 3 实际代表“第三档”,不是“第三名”。业务上想取“前三档”,RANK() 的 3 却跳过了 2,语义断裂。
-
DENSE_RANK()在同样数据下给出[1, 1, 2, 2, 3],dense_rank 稳定覆盖全部三档,无歧义 - 报表里写“A档(第1名)、B档(第2名)、C档(第3名)”,
DENSE_RANK()的输出天然匹配这个映射 -
RANK()的1,1,3容易让业务方追问:“第2名去哪了?”——这不是数据错,是函数语义和业务理解错位
DENSE_RANK() 的 PARTITION BY 行为更可控
按部门分组排名时,DENSE_RANK() OVER (PARTITION BY dept_id ORDER BY salary DESC) 每个部门都从 1 开始、连续编号。哪怕某部门只有两人并列第一,另一部门有五人分四档,各组的档位数仍保持可比性(都是 1→2→3…)。
-
RANK()在小分组里可能只出现1,1,4,导致跨部门比较时档位数量失真 - 做绩效分级(S/A/B/C)时,必须保证每档都有编号,且不能缺档——
DENSE_RANK()天然支持,RANK()需额外补档逻辑 - 如果排序字段存在重复且未加唯一键兜底(如只按
score排),DENSE_RANK()结果仍稳定;但ROW_NUMBER()可能每次执行顺序不同,RANK()虽稳定,档位断层问题照旧
别在 WHERE 里直接用窗口函数
无论选 RANK() 还是 DENSE_RANK(),都不能写成:
SELECT * FROM sales WHERE DENSE_RANK() OVER (ORDER BY amount DESC) <= 3;
这会报错:Invalid use of window function 或字段不存在。窗口函数在 SELECT 阶段才计算,WHERE 已执行完毕。
- 正确写法必须套一层子查询或 CTE
- 漏掉嵌套是新手最常踩的坑,和选哪个函数无关,但一旦出错,容易误以为是
DENSE_RANK()不可用 - 如果还用了
PARTITION BY却漏写,比如本该按region分组,却只写ORDER BY sales,结果就变成全表统一排名,业务逻辑全歪
真正容易被忽略的点是:跳不跳号本身不改变函数性能,也不影响语法,但它直接决定你写的 WHERE dense_rank <= N 是不是真能代表“前 N 档”——而业务要的往往不是“名次”,是“档位”。
相关文章
- 刀剑缭乱2026公测兑换码大全一览 07-05
- 崩坏星穹铁道4.0卡池7个新角色一览 07-05
- 明日方舟终末地开服工业蓝图一览 工业蓝图作用与使用思路解析 07-05
- 原神梦之树怎么开启 梦之树开启条件 07-05
- 帕瓦勇者传说持续伤害阵容搭配推荐 07-05
- 明日方舟:终末地全新玩法 蚀像寻遗怎么玩介绍 07-05