在销售数据分析工作中,经常需要对比不同统计周期下各省份的销售额排名变化,比如对比2024年第一季度和第二季度的省份销售额排名差异,明确哪些省份排名上升、哪些下降。通过SQL的窗口函数可以高效完成这类计算,核心是先分别计算两个周期的省份排名,再进行关联对比。

核心函数说明
实现排名对比的核心是使用RANK()窗口函数,该函数会对指定分组内的数据进行排序并生成排名,相同数值会得到相同排名,后续排名会跳过重复数量的位置。基本语法如下:
-- RANK函数基本语法 RANK() OVER (PARTITION BY 分组字段 ORDER BY 排序字段 DESC/ASC) AS 排名别名
除了RANK(),还可以根据需求选择DENSE_RANK()(并列后不跳过后续排名)或者ROW_NUMBER()(无并列排名,按顺序生成唯一序号),本文以RANK()为例演示。
实现步骤拆解
计算前后两次排名变化分为三个核心步骤:
- 第一步:分别计算第一次统计周期的省份销售额排名
- 第二步:分别计算第二次统计周期的省份销售额排名
- 第三步:将两个排名结果按省份关联,计算排名差值
完整示例演示
假设我们有销售数据表province_sales,表结构如下:
| 字段名 | 类型 | 说明 |
|---|---|---|
| province | varchar | 省份名称 |
| period | varchar | 统计周期,比如Q1、Q2 |
| sales_amount | decimal | 销售额 |
1. 计算第一次周期(Q1)的省份排名
-- 计算Q1各省份销售额排名
SELECT
province,
sales_amount,
RANK() OVER (ORDER BY sales_amount DESC) AS q1_rank
FROM province_sales
WHERE period = 'Q1'
2. 计算第二次周期(Q2)的省份排名
-- 计算Q2各省份销售额排名
SELECT
province,
sales_amount,
RANK() OVER (ORDER BY sales_amount DESC) AS q2_rank
FROM province_sales
WHERE period = 'Q2'
3. 关联两次排名计算变化
将两个子查询按省份关联,计算排名差值,差值正数表示排名上升,负数表示排名下降,0表示排名不变:
WITH q1_rank_data AS (
-- Q1排名子查询
SELECT
province,
sales_amount AS q1_sales,
RANK() OVER (ORDER BY sales_amount DESC) AS q1_rank
FROM province_sales
WHERE period = 'Q1'
),
q2_rank_data AS (
-- Q2排名子查询
SELECT
province,
sales_amount AS q2_sales,
RANK() OVER (ORDER BY sales_amount DESC) AS q2_rank
FROM province_sales
WHERE period = 'Q2'
)
SELECT
COALESCE(q1.province, q2.province) AS province,
q1.q1_sales,
q1.q1_rank,
q2.q2_sales,
q2.q2_rank,
-- 计算排名变化,q1_rank - q2_rank,正数表示排名上升
(q1.q1_rank - q2.q2_rank) AS rank_change
FROM q1_rank_data q1
FULL OUTER JOIN q2_rank_data q2
ON q1.province = q2.province
ORDER BY q2.q2_rank ASC
特殊情况处理
如果某个省份只在其中一个周期有数据,使用FULL OUTER JOIN可以保证该省份不被遗漏,COALESCE函数用于取两个周期中非空省份名称。如果存在并列排名的情况,RANK()函数会自动处理并列逻辑,计算出的排名变化也会符合并列排名的实际含义。
如果需要使用DENSE_RANK()替代RANK(),只需要把两个子查询中的RANK()替换为DENSE_RANK()即可,其他逻辑不需要调整。