如何用DENSE_RANK函数实现SQL查询中每组前三名的长尾词需求?
- 内容介绍
- 相关推荐
本文共计843个文字,预计阅读时间需要4分钟。
由于需要处理并列情况,如果第2、3名分数相同,则使用DENSE_RANK()函数将它们都标记为2,下一名标记为3;而使用ROW_NUMBER()函数则强制编号为2和3,导致实际取4条记录。业务上常说的前三名通常允许并列,如得分前3名的用户,而不是任意3个用户。
常见错误现象:ROW_NUMBER() OVER (PARTITION BY dept ORDER BY score DESC) 在有并列时漏掉同分者,或误取超过3条。
-
DENSE_RANK()编号连续、不跳过:1,2,2,3,3,4… -
RANK()会跳号:1,2,2,4,4,6…(中间缺3/5)——不适合“取前三”语义 - 必须配合子查询或CTE,不能直接在WHERE中引用窗口函数结果
标准写法:用CTE + DENSE_RANK() + 过滤
窗口函数不能出现在WHERE子句里,所以得先算排名,再过滤。CTE最清晰,也兼容绝大多数主流数据库(PostgreSQL、SQL Server、Oracle、MySQL 8.0+)。
本文共计843个文字,预计阅读时间需要4分钟。
由于需要处理并列情况,如果第2、3名分数相同,则使用DENSE_RANK()函数将它们都标记为2,下一名标记为3;而使用ROW_NUMBER()函数则强制编号为2和3,导致实际取4条记录。业务上常说的前三名通常允许并列,如得分前3名的用户,而不是任意3个用户。
常见错误现象:ROW_NUMBER() OVER (PARTITION BY dept ORDER BY score DESC) 在有并列时漏掉同分者,或误取超过3条。
-
DENSE_RANK()编号连续、不跳过:1,2,2,3,3,4… -
RANK()会跳号:1,2,2,4,4,6…(中间缺3/5)——不适合“取前三”语义 - 必须配合子查询或CTE,不能直接在WHERE中引用窗口函数结果
标准写法:用CTE + DENSE_RANK() + 过滤
窗口函数不能出现在WHERE子句里,所以得先算排名,再过滤。CTE最清晰,也兼容绝大多数主流数据库(PostgreSQL、SQL Server、Oracle、MySQL 8.0+)。

