SQL如何实现动态排名统计 掌握DENSE_RANK排序逻辑
DENSE_RANK() 实现“并列不跳号”排名,与ROW_NUMBER()(强制唯一)和RANK()(并列跳号)本质不同;必须配合OVER(ORDER BY...)使用,不可与GROUP BY混用,需通过CTE或子查询先聚合再排名。为什么 DENSE_RANK() 不是 ORDER BY + ROW_NUMBER()?因为 DENSE_RANK() 的核心是「并列不跳号」,而 ROW_NUMBER() 强制唯一编号,RANK() 并列但会跳号。比如分数 [100, 95, 95, 90],三者结果分别是:[1,2,2,3]、[1,2,3,4]、[1,2,2,4]。实际做销售榜、年级排名时,跳号(RANK)会让第 3 名看起来像“断层”,用户困惑;而 ROW_NUMBER 把并列两人硬拆成第 2 和第 3,违背业务语义。实操建议:DENSE_RANK() 必须配合 OVER (ORDER BY ...),不能单独用排序字段允许多列,如 OVER (ORDER BY dept_id, salary DESC),先按部门再按薪资如果想按组内排名,必须加 PARTITION BY,否则全表统排GROUP BY 后还能用 DENSE_RANK() 吗?不能直接用。一旦用了 GROUP BY,非聚合字段不可引用,而 DENSE_RANK() 是窗口函数,依赖原始行粒度。常见错误是写成:SELECT dept_id, DENSE_RANK() OVER (ORDER BY AVG(salary)) FROM emp GROUP BY dept_id;这会报错:column "salary" must appear in the GROUP BY clause or be used in an aggregate function。根本矛盾在于:窗口函数运行在「分组前」的行集上,聚合后只剩一行,窗口无意义。正确做法分两步:先用子查询或 CTE 算出每组聚合值(如 AVG(salary)),保留 dept_id在外层对这个结果集用 DENSE_RANK() OVER (ORDER BY avg_salary)示例: Felvin AI无代码市场,只需一个提示快速构建应用程序
