跳至内容

SQL RANK():如何组织行(含示例)

学习如何使用 SQL RANK() 函数为行分配名次、处理并列,并与 DENSE_RANK() 和 ROW_NUMBER() 进行比较。
更新 2026年5月4日  · 6分钟

在使用 SQL 时,排序数据很简单,您可以轻松使用 ORDER BY 对行进行排列。不过,仅仅排序并不能告诉您每一行在该顺序中的具体位置。这就是排名发挥作用的地方。与其只是查看已排序的数据,您可能希望根据特定条件为每一行分配第 1、2、3 名之类的位置。

RANK() 函数通过根据定义的顺序为每一行分配数值名次来解决这个问题。RANK() 属于 SQL 窗口函数,它允许您在一组行上执行计算,同时仍返回逐行结果。

在本教程中,我将向您展示 RANK() 的语法、实际示例、了解它如何处理并列,并看看它与 DENSE_RANK()ROW_NUMBER() 等类似函数的比较。

如果您是 SQL 新手,请从我们的 Introduction to SQL 课程开始;如果您已有一定经验,可选择 Intermediate SQL 课程。

什么是 SQL RANK() 函数?

SQL 的 RANK() 函数是一种窗口函数,可根据指定的顺序为每一行分配名次。名次完全由窗口函数内部的 ORDER BY 决定。因此,它会根据 ORDER BY 子句为每一行给出 1、2、3 等位置。

需要注意的是,当您使用 RANK() 时:

  • 具有相同值的行(并列)会获得相同的名次。
  • 出现并列时,排名序列会出现空缺。例如,如果两行的名次为 2,下一名将是 4 而不是 3。

SQL RANK() 语法

RANK() 函数的基本语法为:

RANK() OVER (ORDER BY column)

其中:

  • OVER 子句:定义函数要操作的窗口(行集)。

  • ORDER BY:确定如何应用排名,例如从高到低。

  • PARTITION BY(可选):将数据划分为分组,并在每个组内分别排名。

以下是带有 PARTITION BY 子句的 RANK() 语法:

RANK() OVER (PARTITION BY column1 ORDER BY column2)

SQL RANK() 函数在主流数据库中均得到广泛支持,包括 PostgreSQL、MySQL(8.0+)、Microsoft SQL Server 和 Oracle Database。由于它是 ANSI SQL 标准的一部分,因此各系统的语法基本一致。

SQL RANK() 基本示例

既然您已经了解了 RANK() 函数的语法,我来展示一个简单的工作示例。

假设您有一个 employees 表,其中包含每位员工的薪资信息。

Employee table.

您可以使用以下查询根据薪资为员工排名。

-- Rank employees by salary
SELECT 
    name,
    salary,
    RANK() OVER (ORDER BY salary DESC) AS rank_position
FROM employees;

在上述查询中,行按薪资从高到低排序,因此最高薪资获得名次 1。当两行的薪资相同,它们将获得相同的名次。

Using RANK() function in SQL.

您会注意到,如果两行具有相同的值,它们会得到相同的名次。

随后会跳过下一个名次。SQL 通过跳过下一个名次值来处理并列。

我建议您学习我们的 Introduction to SQL Server 课程,以进一步学习分组与数据聚合。

结合 PARTITION BY 的 SQL RANK()

如前所述,PARTITION BY 子句允许您在分组内应用排名,而不是针对整个数据集。

在下面的示例中,员工按 department 分组,并且每个部门内的排名都会重新开始。因此,每个组都有自己独立的排名序列。

-- Rank employees within each department
SELECT 
    name,
    department,
    salary,
    RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS dept_rank
FROM employees;

Using SQL RANK() with PARTITION BY

从上述结果可以看到,在“Sales”中,Emily Johnson 和 Michael Brown 并列第 1 名;在“HR”中,William Miller 和 Olivia Wilson 也并列第 1 名。

SQL RANK() vs. DENSE_RANK() vs. ROW_NUMBER()

在 SQL 中进行排名时,您可以选择使用 RANK()DENSE_RANK()ROW_NUMBER()。这些函数看起来相似,但其行为如下:

  • RANK():并列共享同一名次,因此并列后会出现空缺。

  • DENSE_RANK():并列共享同一名次,但排名无空缺。

  • ROW_NUMBER():即使值相同,每一行也会获得唯一编号,不存在并列。

为更好地理解这些差异,让我们使用下面的查询进行并排比较:

-- Compare RANK() vs DENSE_RANK() vs ROW_NUMBER()
SELECT 
    name,
    salary,

    RANK() OVER (ORDER BY salary DESC) AS rank_val,          -- allows gaps after ties

    DENSE_RANK() OVER (ORDER BY salary DESC) AS dense_rank1,  -- no gaps, consecutive ranks

    ROW_NUMBER() OVER (ORDER BY salary DESC) AS row_num      -- always unique sequence

FROM employees;

SQL RANK() vs. DENSE_RANK() vs. ROW_NUMBER()

基于上述结果,您可以:

  • 当名次位置本身很重要且可接受空缺时,使用 RANK()

  • 当您需要连续的排名时,使用 DENSE_RANK()

  • 当每一行都必须拥有唯一编号(例如数据分页)时,使用 ROW_NUMBER()

何时使用 SQL RANK()

当您希望对数据进行排序并自然处理并列时,SQL RANK() 函数最为有用。我也发现它在以下用例中特别重要:

  • 排行榜:当您希望根据得分为玩家或用户排名,并允许同分并列时。
  • 销售业绩排名:当您希望按收入识别表现最好的员工或区域,即使结果相同也能体现。
  • 识别 Top-N 值:适用于“前 3 名薪资”之类的查询,尤其是在应包含并列时。

SQL RANK() 的常见错误

以下是我在使用 SQL RANK() 函数时遇到的一些错误,以及如何避免它们:

  • 忽略 ORDER BY:没有 ORDER BY 子句,排名就没有明确逻辑,可能返回意外结果。

  • 误解并列行为:作为初学者,您可能期望 1、2、2、3,但 RANK() 会在排名中产生空缺(1、2、2、4)。

  • 在需要 ROW_NUMBER() 时使用 RANK():如果您需要唯一的连续值,ROW_NUMBER() 是更好的选择。

  • 在需要时未使用 PARTITION BY:没有分区时,排名会在全局范围内应用,而不是在组内应用。

使用 SQL RANK() 的最佳实践

为使查询简洁并确保获得预期结果,使用 SQL RANK() 函数时我建议遵循以下最佳实践:

  • 始终定义清晰的排序:ORDER BY 子句中明确指定,如 DESC,以避免含糊的排名。

  • 选择正确的排名函数:根据您希望如何处理并列,选择 RANK()DENSE_RANK()ROW_NUMBER()

  • 测试并列场景:在上线前,验证当存在重复值时数据的表现。

  • 结合筛选使用:由于您无法在 WHERE 子句中直接使用 RANK(),当要筛选“Top N”时,必须将排名查询包装在子查询(Subquery)CTE 中。

结论

RANK() 是在 SQL 中进行有序比较的实用工具,尤其当您需要反映现实场景(如数值相等)的结果时。理解它如何处理并列、以及为何名次会重复并跳号,对于准确分析非常重要。一旦掌握其行为,您就能根据具体用例,在 DENSE_RANK()ROW_NUMBER() 等替代方案之间做出合适选择。

现在您已经学会了如何在 SQL 中进行排名,如果您希望成为一名熟练的数据分析师并掌握必要技能,建议查看我们的 Associate Data Analyst in SQL 职业路径。此外,如果您想学习如何使用 SQL 构建专业的仪表板,我们的 Reporting in SQL 课程也很合适。

SQL RANK() 常见问答

RANK() 与 ORDER BY 有何不同?

ORDER BY 只对行进行排序,而 RANK() 会在排序之后为每一行分配数字名次。

为什么 RANK() 结果中会有空缺?

在出现并列时,多个行共享相同名次,从而将下一个名次向后推,因此 RANK() 的结果中可能出现空缺。

RANK() 与 DENSE_RANK() 有何区别?

RANK() 在并列后会产生空缺,而 DENSE_RANK() 会分配连续的名次,不会出现空缺。

RANK() 与 ROW_NUMBER() 有何区别?

RANK() 允许并列,但 ROW_NUMBER() 会为每一行分配唯一编号,无论是否有重复。

所有数据库都支持 RANK() 吗?

大多数现代数据库都支持 RANK(),包括 PostgreSQL、MySQL(8.0+)、Microsoft SQL Server 和 Oracle Database。

主题

与 DataCamp 一起学习 SQL

Courses

Data Manipulation in SQL

4小时
319.9K
Master the complex SQL queries necessary to answer a wide variety of data science questions and prepare robust data sets for analysis in PostgreSQL.
查看详情Right Arrow
开始课程
查看更多Right Arrow