SQL窗口函数可以在不改变原表行数的前提下,对数据进行分组内的聚合、排名等计算,结合分组逻辑可模拟出数据透视的效果,比传统的子查询嵌套方式更简洁高效。

窗口函数基础语法
窗口函数的核心结构由函数本身和OVER子句组成,OVER子句用于定义数据的分组和排序规则,基本语法如下:
-- 窗口函数基本语法结构
函数名(参数) OVER (
[PARTITION BY 分组列1, 分组列2...]
[ORDER BY 排序列1 [ASC|DESC], 排序列2 [ASC|DESC]...]
[ROWS|RANGE BETWEEN 边界1 AND 边界2]
)
其中PARTITION BY用于指定分组逻辑,类似聚合查询中的GROUP BY,但不会压缩行数;ORDER BY用于指定分组内的排序规则;最后的窗口边界子句可选,用于限制计算的数据范围。
结合分组聚合实现透视效果
传统数据透视需要把行数据转为列数据,使用窗口函数配合CASE表达式可以实现类似效果,同时保留明细行的其他信息。以下示例基于销售数据表sales,表结构包含sale_date(销售日期)、region(地区)、category(品类)、amount(销售额)。
需求:统计每个地区各品类的销售额,同时展示每个地区的总销售额和品类销售额占比。
-- 计算每个地区的总销售额和品类销售额占比
SELECT
sale_date,
region,
category,
amount,
-- 地区总销售额,按地区分组聚合
SUM(amount) OVER (PARTITION BY region) AS region_total_amount,
-- 品类在地区内的销售额,按地区和品类分组聚合
SUM(amount) OVER (PARTITION BY region, category) AS category_region_amount,
-- 计算品类销售额占地区总销售额的比例
ROUND(SUM(amount) OVER (PARTITION BY region, category) * 1.0 / SUM(amount) OVER (PARTITION BY region), 4) AS category_ratio
FROM sales
ORDER BY region, category;
上述查询既保留了原始的每行销售明细,又输出了类似透视表的分组统计结果,无需使用GROUP BY压缩行数,后续还可以基于这些计算结果做进一步筛选。
结合排名实现分组内排序
窗口函数中的排名函数可以和分组聚合结合,实现分组内的数据排序和TopN筛选,进一步完善透视效果的多维度分析能力。常用的排名函数有ROW_NUMBER、RANK、DENSE_RANK,三者的区别如下:
| 函数名 | 排序规则 | 相同值处理 |
|---|---|---|
| ROW_NUMBER | 按顺序生成唯一序号 | 相同值也会生成不同序号 |
| RANK | 按值排序生成排名 | 相同值排名相同,下一个排名跳过重复数量 |
| DENSE_RANK | 按值排序生成排名 | 相同值排名相同,下一个排名连续 |
以下示例实现查询每个地区销售额前3的品类:
-- 查询每个地区销售额前3的品类
WITH category_sale AS (
SELECT
region,
category,
SUM(amount) AS category_total_amount,
-- 按地区分组,按品类销售额降序排名
DENSE_RANK() OVER (PARTITION BY region ORDER BY SUM(amount) DESC) AS sale_rank
FROM sales
GROUP BY region, category
)
SELECT region, category, category_total_amount, sale_rank
FROM category_sale
WHERE sale_rank <= 3
ORDER BY region, sale_rank;
这里先通过普通GROUP BY计算每个地区各品类的总销售额,再用窗口函数DENSE_RANK在分组内按销售额排名,最后筛选排名前3的记录,实现了分组内的TopN透视分析。
注意事项
- 窗口函数只能出现在SELECT子句和ORDER BY子句中,不能用于WHERE、GROUP BY等子句。
- 不同数据库对窗口函数的支持程度不同,MySQL8.0+、PostgreSQL、SQL Server、Oracle均支持标准窗口函数,低版本数据库可能需要用其他方式实现。
- 如果不需要保留原始明细行,也可以结合GROUP BY使用聚合函数,再用窗口函数做二次计算,减少数据量提升查询效率。
窗口函数的核心是OVER子句的分组和排序定义,理解PARTITION BY和ORDER BY的作用,就能灵活组合出各种数据透视和分组分析逻辑。