跳到主要内容

SQL窗口函数

介绍

SQL窗口函数(Window Functions)是一种强大的工具,允许你在不改变查询结果集的情况下,对数据进行复杂的计算和分析。与普通的聚合函数(如 SUMAVG)不同,窗口函数不会将多行合并为一行,而是为每一行返回一个计算结果。这使得窗口函数非常适合用于排名、累积计算、移动平均等场景。

窗口函数的核心概念是“窗口”(Window),它定义了函数计算的范围。窗口可以是整个表、分组后的数据,或者基于行的滑动窗口。

基本语法

窗口函数的基本语法如下:

sql
<窗口函数> OVER (
[PARTITION BY <列名>]
[ORDER BY <列名>]
[ROWS BETWEEN <起始行> AND <结束行>]
)
  • PARTITION BY:将数据分组,类似于 GROUP BY,但不会合并行。
  • ORDER BY:定义窗口内数据的排序方式。
  • ROWS BETWEEN:定义窗口的范围,可以是当前行的前后几行,或者整个分区。

常用窗口函数

以下是一些常用的窗口函数:

  1. ROW_NUMBER():为每一行分配一个唯一的序号。
  2. RANK():为每一行分配一个排名,相同值会有相同的排名,后续排名会跳过。
  3. DENSE_RANK():与 RANK() 类似,但不会跳过后续排名。
  4. SUM()AVG()MIN()MAX():在窗口内计算聚合值。
  5. LEAD()LAG():访问当前行之前或之后的行的值。

示例

假设我们有一个销售数据表 sales,结构如下:

sql
CREATE TABLE sales (
id INT,
salesperson VARCHAR(50),
sale_date DATE,
amount DECIMAL(10, 2)
);

示例1:计算每个销售人员的累计销售额

sql
SELECT 
salesperson,
sale_date,
amount,
SUM(amount) OVER (PARTITION BY salesperson ORDER BY sale_date) AS cumulative_sales
FROM
sales;

输出:

salespersonsale_dateamountcumulative_sales
Alice2023-01-01100.00100.00
Alice2023-01-02200.00300.00
Bob2023-01-01150.00150.00
Bob2023-01-03250.00400.00

示例2:计算每个销售人员的销售额排名

sql
SELECT 
salesperson,
sale_date,
amount,
RANK() OVER (PARTITION BY salesperson ORDER BY amount DESC) AS sales_rank
FROM
sales;

输出:

salespersonsale_dateamountsales_rank
Alice2023-01-02200.001
Alice2023-01-01100.002
Bob2023-01-03250.001
Bob2023-01-01150.002

实际应用场景

场景1:计算移动平均

假设你想计算每个销售人员的3天移动平均销售额:

sql
SELECT 
salesperson,
sale_date,
amount,
AVG(amount) OVER (
PARTITION BY salesperson
ORDER BY sale_date
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
) AS moving_avg
FROM
sales;

场景2:查找每个销售人员的最大销售额

sql
SELECT 
salesperson,
sale_date,
amount,
MAX(amount) OVER (PARTITION BY salesperson) AS max_sale
FROM
sales;

总结

SQL窗口函数为数据分析提供了强大的工具,允许你在不改变数据行的情况下进行复杂的计算。通过 PARTITION BYORDER BYROWS BETWEEN,你可以灵活地定义窗口的范围和排序方式。掌握窗口函数将极大地提升你在SQL中的数据处理能力。

附加资源与练习

  • 练习1:尝试使用 LEAD()LAG() 函数,计算每个销售人员的销售额与前一天的差异。
  • 练习2:使用 DENSE_RANK() 函数,为每个销售人员的销售额分配排名,并观察与 RANK() 的区别。
提示

如果你对窗口函数的使用还有疑问,建议多尝试不同的查询,并结合实际数据进行练习。实践是掌握SQL窗口函数的最佳方式!