悠悠楠杉
SQL中SUM()OVER分组求和详解:窗口函数的强大之处
引言:为什么需要窗口函数?
在日常数据分析工作中,我们经常遇到这样的场景:既要计算总和,又要保留原始数据行;既要看到整体情况,又要分析局部细节。这正是SQL窗口函数大显身手的地方。今天我们就来深入探讨SUM() OVER这个强大的窗口函数用法。
一、SUM() OVER基础语法解析
SUM() OVER的基本语法结构如下:
sql
SUM(column_name) OVER (
[PARTITION BY partition_expression]
[ORDER BY sort_expression [ASC|DESC]]
[frame_clause]
)
1.1 简单分组求和
最简单的用法是只使用PARTITION BY子句:
sql
SELECT
department_id,
employee_name,
salary,
SUM(salary) OVER (PARTITION BY department_id) AS dept_total_salary
FROM employees;
这个查询会计算每个部门的工资总额,同时保留每位员工的详细信息。
1.2 添加排序的累计求和
当加入ORDER BY子句时,SUM() OVER就变成了累计求和:
sql
SELECT
order_date,
product_id,
daily_sales,
SUM(daily_sales) OVER (PARTITION BY product_id ORDER BY order_date) AS running_total
FROM sales_data;
这样可以得到每个产品按日期累计的销售总额。
二、高级用法详解
2.1 自定义窗口范围
通过frame_clause可以精确控制求和范围:
sql
-- 当前行及前两行的总和
SELECT
date,
revenue,
SUM(revenue) OVER (ORDER BY date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS 3day_moving_avg
FROM daily_revenue;
常用窗口范围:
- ROWS BETWEEN N PRECEDING AND CURRENT ROW
:前N行到当前行
- ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
:从开始到当前行(默认)
- ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
:从当前行到最后
2.2 多列分组
PARTITION BY支持多列组合:
sql
SELECT
year,
quarter,
region,
sales,
SUM(sales) OVER (PARTITION BY year, quarter, region) AS regional_quarterly_sales
FROM sales_records;
三、实际应用场景
3.1 销售数据分析
sql
-- 计算每位销售员的销售额占团队比例
SELECT
salesperson,
sale_amount,
team,
SUM(sale_amount) OVER (PARTITION BY team) AS team_total,
sale_amount / SUM(sale_amount) OVER (PARTITION BY team) * 100 AS contribution_percentage
FROM sales_transactions;
3.2 库存管理
sql
-- 计算产品库存的累计入库和出库
SELECT
product_id,
transaction_date,
transaction_type,
quantity,
SUM(CASE WHEN transaction_type = 'IN' THEN quantity ELSE 0 END)
OVER (PARTITION BY product_id ORDER BY transaction_date) AS cumulative_in,
SUM(CASE WHEN transaction_type = 'OUT' THEN quantity ELSE 0 END)
OVER (PARTITION BY product_id ORDER BY transaction_date) AS cumulative_out
FROM inventory_transactions;
四、性能优化建议
- 合理使用PARTITION BY:过多的分组列会增加计算负担
- 谨慎使用ORDER BY:可能导致全表排序,在大数据量时性能下降
- 考虑索引:为PARTITION BY和ORDER BY涉及的列建立索引
- 替代方案:对于简单分组求和,GROUP BY可能更高效
五、与其他窗口函数的比较
SUM() OVER只是众多窗口函数中的一个,其他常用函数包括:
- AVG() OVER
:计算移动平均
- ROW_NUMBER() OVER
:生成行号
- RANK() OVER
:计算排名
- LEAD()/LAG() OVER
:访问相邻行数据
这些函数可以组合使用,实现复杂的分析需求。
结语:窗口函数的思考
SUM() OVER为代表的窗口函数,打破了传统SQL要么聚合要么明细的二元对立,实现了"既要又要"的数据分析需求。掌握好窗口函数,能让你的SQL查询能力提升一个层次,写出更优雅、更高效的分析语句。
在实际工作中,建议从简单场景开始练习,逐步尝试更复杂的窗口定义,最终你会发现自己已经离不开这些强大的分析工具了。