




使用窗口函数ROW_NUMBER()、RANK()或DENSE_RANK()配合PARTITION BY实现分组内排序,保留每行记录;如查各部门工资前3员工:SELECT * FROM (SELECT name,dept,salary,ROW_NUMBER() OVER(PARTITION BY dept ORDER BY salary DESC) AS rn FROM employees) tWHERE rn
SQL 实现分组内排序,主要靠窗口函数 ROW_NUMBER()、RANK() 或 DENSE_RANK() 配合 PARTITION BY 子句,而不是用 GROUP BY —— 因为 GROUP BY 会聚合数据,无法保留每行原始记录来排序。
这是最常用、最直接的方式:按指定字段分组,在每组内部按另一字段排序,并为每行生成序号。
SELECT * FROM (
SELECT name, dept, salary,
ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESC) AS rn
FROM employees
) t WHERE rn
三者都支持分组内排序,但处理并列的方式不同:
比如某部门三人薪资为 15000、12000、12000:
ROW_NUMBER → 1,2,3;RANK → 1,2,2;DENSE_RANK → 1,2,2
窗口函数不能直接在 WHERE 中使用(因为执行顺序晚于 WHERE),必须嵌套子查询或 CTE:
WITH ranked AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY category ORDER BY score DESC) AS seq
FROM products
)
SELECT name, category, score FROM ranked WHERE seq = 1;
只能用自连接或相关子查询模拟,性能较差,且逻辑复杂:
不复杂但容易忽略:分组内排序本质是“每行独立计算位置”,不是聚合,所以别用 GROUP BY 去尝试实现。