SQL关键字三分钟入门:RANK() —— 窗口函数
在数据分析过程中,我们经常需要对数据进行排序,并根据某些条件给记录分配排名。例如:
- 按照销售额为销售人员排名;
- 根据考试成绩对学生进行排序;
- 依据访问量给网站页面排序。
这时候就需要用到 SQL 中非常强大的窗口函数 —— RANK()
!
它可以帮助我们轻松地为查询结果集中的每一行分配一个排名,特别适合处理涉及排序和分组的数据分析任务。
什么是 RANK()?
RANK()
是 SQL 中用于计算分区或整个结果集中行的排名的窗口函数。它会根据指定的排序规则为每条记录分配一个排名值,允许存在并列排名(即相同的值会有相同的排名,但接下来的排名会跳过相应的数字)。
你可以把它理解为:“按照某个标准给每条记录打上排名标签”。
基本语法
SELECT column1, column2, ..., RANK() OVER ([PARTITION BY partition_column]ORDER BY sort_column [ASC|DESC], ...
) AS rank_number
FROM table_name;
PARTITION BY
(可选):定义如何将数据划分为不同的分区(类似于GROUP BY
),每个分区独立进行排名。ORDER BY
:指定用于决定排名顺序的列及其方向(升序或降序)。
示例讲解
假设我们有一个 sales
表,记录了销售人员的业绩信息:
employee_id | name | sales_amount |
---|---|---|
1 | 张三 | 5000 |
2 | 李四 | 3000 |
3 | 王五 | 4000 |
4 | 赵六 | 4000 |
5 | 孙七 | 6000 |
示例1:按销售额对所有员工进行排名
SELECT name, sales_amount,
RANK() OVER (ORDER BY sales_amount DESC) AS rank_number
FROM sales;
结果:
name | sales_amount | rank_number |
---|---|---|
孙七 | 6000 | 1 |
张三 | 5000 | 2 |
王五 | 4000 | 3 |
赵六 | 4000 | 3 |
李四 | 3000 | 5 |
注意:因为王五和赵六的销售额相同,他们的排名都是3,而下一位李四的排名则跳到了5(而不是4)。
示例2:按部门对员工进行排名(使用 PARTITION BY)
假设我们增加了一个 department
列来表示员工所属的部门:
employee_id | name | department | sales_amount |
---|---|---|---|
1 | 张三 | 销售部 | 5000 |
2 | 李四 | 销售部 | 3000 |
3 | 王五 | 技术部 | 4000 |
4 | 赵六 | 技术部 | 4000 |
5 | 孙七 | 销售部 | 6000 |
SELECT name, department, sales_amount,
RANK() OVER (PARTITION BY department ORDER BY sales_amount DESC) AS rank_number
FROM sales;
结果:
name | department | sales_amount | rank_number |
---|---|---|---|
孙七 | 销售部 | 6000 | 1 |
张三 | 销售部 | 5000 | 2 |
李四 | 销售部 | 3000 | 3 |
王五 | 技术部 | 4000 | 1 |
赵六 | 技术部 | 4000 | 1 |
这里我们按部门进行了划分,然后在每个部门内部根据销售额进行排名。
示例3:结合其他聚合函数使用
有时候你可能还需要同时计算一些汇总信息,比如总销售额、平均销售额等。下面的例子展示了如何同时显示排名和销售总额:
SELECT name, sales_amount,
SUM(sales_amount) OVER () AS total_sales,
RANK() OVER (ORDER BY sales_amount DESC) AS rank_number
FROM sales;
结果:
name | sales_amount | total_sales | rank_number |
---|---|---|---|
孙七 | 6000 | 22000 | 1 |
张三 | 5000 | 22000 | 2 |
王五 | 4000 | 22000 | 3 |
赵六 | 4000 | 22000 | 3 |
李四 | 3000 | 22000 | 5 |
注意
对比项 | 使用建议 |
---|---|
并列排名 | 如果多个记录有相同的排序值,它们会被赋予相同的排名,且下一个排名会跳过相应的数字 |
不同的排名函数 | - DENSE_RANK() :与 RANK() 类似,但不会跳过排名数字 |
- ROW_NUMBER() :总是给出连续的排名数字,即使有相同的排序值 | |
性能优化 | 尽量减少 PARTITION BY 的范围以提高性能 |
数据一致性 | 在执行复杂的排名操作时,确保数据的一致性和准确性 |
总结对比表
场景 | SQL 示例 |
---|---|
按单一条件排名 | SELECT ..., RANK() OVER (ORDER BY sales_amount DESC) AS rank FROM sales; |
按部门内条件排名 | SELECT ..., RANK() OVER (PARTITION BY department ORDER BY sales_amount DESC) AS rank FROM sales; |
结合其他聚合函数使用 | SELECT ..., SUM(sales_amount) OVER () AS total_sales, RANK() OVER (ORDER BY sales_amount DESC) AS rank FROM sales; |