应选RANK()当需并列排名(相同值同名次且后续跳号),选ROW_NUMBER()当需唯一连续编号;业务中若要求“并列不跳号”实为误述,正确应为DENSE_RANK(),RANK()典型场景是体育排名,ROW_NUMBER()适用于分页、去重。

MySQL 8.0+ 用 RANK() 还是 ROW_NUMBER()?
选哪个取决于你是否允许并列。比如分数相同都算第1名,后续跳过第2名——这是 RANK();如果强制连续编号(相同分数也分第1、第2),就得用 ROW_NUMBER()。实际业务中多数场景要的是“并列不跳号”,所以优先试 RANK()。
示例:按部门分组查薪资前三高的员工
RANK()
-
PARTITION BY字段写错(比如写成GROUP BY习惯,漏掉OVER) - ORDER BY 里混用 ASC/DESC 导致排名逆序(比如想取最高分却写了
ORDER BY salary ASC) - 没加括号包裹子查询,直接在外部 WHERE 里引用
rk报错:“column does not exist”
SQLite 或老版本 MySQL(5.7)怎么兼容?
没有窗口函数就只能靠相关子查询,但性能随数据量增长急剧下降,万级数据就明显卡顿。
核心思路:对每条记录,统计同组中比它分数高(或等于且 ID 更小)的记录数 ≤ 2。
SELECT e1.dept, e1.name, e1.salary
FROM employees e1
WHERE (
SELECT COUNT(*)
FROM employees e2
WHERE e2.dept = e1.dept
AND (e2.salary > e1.salary
OR (e2.salary = e1.salary AND e2.id
<p>注意点:</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/ai/2250" title="光子AI"><img
src="https://img.php.cn/upload/ai_manual/000/000/000/175680072127314.png" alt="光子AI" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/ai/2250" title="光子AI" class="overflowclass">光子AI</a>
<p class="overflowclass">一款AI视频创作工具,主要用于AI电商服饰商拍平台,适合需要提升相关任务效率的用户。</p>
</div>
<a rel="nofollow" href="/ai/2250" title="光子AI" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
- 必须用
AND e2.id 处理并列情况,否则相同分数全挤进结果 - 索引一定要建在
(dept, salary, id)上,否则慢得没法用 - MySQL 5.7 默认不支持在子查询里引用外层表别名(报错 “Unknown column”),得改写成 JOIN 形式或升级到 8.0
为什么 LIMIT 3 在 GROUP BY 里不管用?
因为 GROUP BY 是聚合操作,LIMIT 是最终结果限制,不是每组限3条。写成 GROUP BY dept LIMIT 3 只会返回任意3个部门的聚合结果,不是每个部门的前3条。
有人试过 GROUP_CONCAT + SUBSTRING_INDEX 拼接再拆解,看似能绕过,但有长度限制(group_concat_max_len 默认 1024)、无法保留原始字段类型、排序不稳定,纯属自找麻烦。
真正要注意的其实是数据倾斜:如果某个部门有上万员工,而其他部门只有几个,RANK() 窗口计算仍会扫描全量,但执行计划里看不到瓶颈在哪——得看 EXPLAIN ANALYZE 的 actual rows 是否远超预期。










