ROW_NUMBER() 的基本语法
```sql
ROW_NUMBER() OVER (
[PARTITION BY partition_expression, ... ]
ORDER BY sort_expression [ASC|DESC], ...
)
```
- PARTITION BY:可选参数,用于将结果集划分为多个分区,在每个分区内部单独进行排序。
- ORDER BY:必需参数,用于指定行号的分配顺序。
示例 1:基本用法
假设我们有一个员工表 `Employees`,包含以下字段:`EmployeeID`, `FirstName`, `LastName`, `Department` 和 `Salary`。我们希望为每个部门的员工按照工资从高到低排序,并分配行号。
```sql
SELECT
EmployeeID,
FirstName,
LastName,
Department,
Salary,
ROW_NUMBER() OVER (PARTITION BY Department ORDER BY Salary DESC) AS RowNum
FROM Employees;
```
在这个查询中,`PARTITION BY Department` 将结果按部门划分,`ORDER BY Salary DESC` 则是在每个部门内按工资降序排列。`ROW_NUMBER()` 会为每个部门内的员工分配一个唯一的行号。
示例 2:限制返回的行数
有时候,你可能只需要返回某个部门中薪水最高的几人。例如,我们需要找出每个部门中薪水最高的3名员工:
```sql
WITH RankedEmployees AS (
SELECT
EmployeeID,
FirstName,
LastName,
Department,
Salary,
ROW_NUMBER() OVER (PARTITION BY Department ORDER BY Salary DESC) AS RowNum
FROM Employees
)
SELECT
FROM RankedEmployees
WHERE RowNum <= 3;
```
这里使用了 `WITH` 子句创建了一个临时的结果集 `RankedEmployees`,然后从中筛选出每个部门中行号小于等于3的记录。
示例 3:结合其他窗口函数
`ROW_NUMBER()` 可以与其他窗口函数如 `RANK()` 或 `DENSE_RANK()` 结合使用。这些函数的区别在于如何处理相同排名的情况。
```sql
SELECT
EmployeeID,
FirstName,
LastName,
Department,
Salary,
ROW_NUMBER() OVER (PARTITION BY Department ORDER BY Salary DESC) AS RowNum,
RANK() OVER (PARTITION BY Department ORDER BY Salary DESC) AS RankNum,
DENSE_RANK() OVER (PARTITION BY Department ORDER BY Salary DESC) AS DenseRankNum
FROM Employees;
```
- ROW_NUMBER():为每个员工分配唯一的行号,即使薪资相同也会有不同的行号。
- RANK():相同的薪资会导致相同的排名,且下一个排名会跳过相应的数字。
- DENSE_RANK():与 `RANK()` 类似,但不会跳过排名。
总结
`ROW_NUMBER()` 是SQL中一个强大的工具,它可以帮助我们在结果集中为每行分配一个唯一的编号。无论是简单的排序还是复杂的分组操作,`ROW_NUMBER()` 都能提供极大的灵活性。通过灵活运用 `PARTITION BY` 和 `ORDER BY` 子句,我们可以实现各种复杂的查询需求。