在电商、零售等业务的数据分析工作中,经常需要统计每个产品的销售额占所有产品总销售额的比例,也就是销售占比,用来判断单个产品的贡献度。传统实现方式需要先查询总销售额,再和产品销售额表做关联计算,逻辑相对复杂,而使用SUM OVER窗口函数可以直接在一次查询中完成总分母的计算,简化整个实现过程。

SUM OVER窗口函数基础语法
SUM OVER是SQL中窗口函数的一种,用于对指定窗口内的数据进行求和计算,基本语法如下:
-- 基础语法结构 SUM(求和字段) OVER (PARTITION BY 分组字段 ORDER BY 排序字段 ROWS 窗口范围)
如果不指定PARTITION BY,则会对全表数据进行求和;如果不指定ORDER BY和窗口范围,则默认对当前分区内的所有行进行求和,这个特性刚好可以用来计算总销售额作为分母。
产品销售占比计算实现步骤
1. 准备测试数据
首先创建产品销售数据表并插入测试数据,表结构包含产品ID、产品名称和销售额三个字段:
-- 创建产品销售表
CREATE TABLE product_sales (
product_id INT,
product_name VARCHAR(50),
sales_amount DECIMAL(10,2)
);
-- 插入测试数据
INSERT INTO product_sales (product_id, product_name, sales_amount) VALUES
(1, '产品A', 1500.00),
(2, '产品B', 3000.00),
(3, '产品C', 2500.00),
(4, '产品D', 1000.00),
(5, '产品E', 2000.00);
2. 使用SUM OVER计算总销售额
通过SUM OVER窗口函数不指定分区条件,直接对全表的sales_amount求和,得到所有产品的总销售额:
-- 查询每个产品销售额和总销售额
SELECT
product_id,
product_name,
sales_amount,
-- 不指定PARTITION BY,对全表销售额求和作为总销售额
SUM(sales_amount) OVER () AS total_sales
FROM product_sales;
上述查询的结果中,每一行都会包含total_sales字段,值为所有产品销售额的总和,也就是10000.00。
3. 计算销售占比
用单个产品的销售额除以总销售额,再乘以100得到百分比形式的销售占比:
-- 计算每个产品的销售占比
SELECT
product_id,
product_name,
sales_amount,
total_sales,
-- 计算占比,保留两位小数
ROUND(sales_amount / total_sales * 100, 2) AS sales_ratio_percent
FROM (
SELECT
product_id,
product_name,
sales_amount,
SUM(sales_amount) OVER () AS total_sales
FROM product_sales
) t;
最终查询结果如下:
| product_id | product_name | sales_amount | total_sales | sales_ratio_percent |
|---|---|---|---|---|
| 1 | 产品A | 1500.00 | 10000.00 | 15.00 |
| 2 | 产品B | 3000.00 | 10000.00 | 30.00 |
| 3 | 产品C | 2500.00 | 10000.00 | 25.00 |
| 4 | 产品D | 1000.00 | 10000.00 | 10.00 |
| 5 | 产品E | 2000.00 | 10000.00 | 20.00 |
传统写法与SUM OVER写法对比
传统计算销售占比的方式需要先查询总销售额,再和产品表做关联:
-- 传统写法
SELECT
p.product_id,
p.product_name,
p.sales_amount,
t.total_sales,
ROUND(p.sales_amount / t.total_sales * 100, 2) AS sales_ratio_percent
FROM product_sales p
-- 关联总销售额子查询
CROSS JOIN (
SELECT SUM(sales_amount) AS total_sales FROM product_sales
) t;
两种写法的差异如下:
- 传统写法需要两次扫描产品表,一次算总销售额,一次取产品数据,而SUM OVER写法只需要一次全表扫描,执行效率更高。
- 传统写法需要额外的子查询和关联操作,查询逻辑更复杂,SUM OVER写法逻辑更简洁,可读性更强。
- 如果后续需要扩展计算逻辑,比如按品类分组计算占比,SUM OVER只需要调整PARTITION BY条件即可,传统写法需要修改子查询和关联条件,改动成本更高。
注意事项
使用SUM OVER计算销售占比时需要注意几个问题:
- 如果销售额字段可能存在NULL值,需要先用COALESCE函数将NULL转换为0,避免计算结果出现NULL。
- 如果总销售额为0,需要做除零判断,避免查询报错,可以通过CASE WHEN语句处理这种情况。
- 不同数据库对窗口函数的支持略有差异,上述语法适用于MySQL 8.0+、PostgreSQL、SQL Server等主流数据库,如果是低版本数据库可能需要调整实现方式。