这篇文章主要介绍了MySQL窗口函数及其在解决分析查询挑战中的实用应用。MySQL从8.0版本开始支持窗口函数,这些函数使你能够以新的、更简单的方式解决查询问题,并提供更好的性能。

假设我们有一个销售表,它存储了员工和财年的销售情况:

CREATE TABLE sales(
 sales_employee VARCHAR(50) NOT NULL,
 fiscal_year INT NOT NULL,
 sale DECIMAL(14,2) NOT NULL,
 PRIMARY KEY(sales_employee,fiscal_year)
);

INSERT INTO sales(sales_employee,fiscal_year,sale)
VALUES('Bob',2016,100),
 ('Bob',2017,150),
 ('Bob',2018,200),
 ('Alice',2016,150),
 ('Alice',2017,100),
 ('Alice',2018,200),
 ('John',2016,200),
 ('John',2017,150),
 ('John',2018,250);

SELECT * FROM sales;

理解窗口函数的一个好方法是从聚合函数开始。聚合函数将多行数据汇总为单个结果行。例如,以下SUM()函数返回所有员工在记录年份的总销售额:

SELECT 
 SUM(sale)
FROM
 sales;

GROUP BY子句允许你将聚合函数应用于一部分行。例如,你可能想计算财年的总销售额:

SELECT 
 fiscal_year, 
 SUM(sale)
FROM
 sales
GROUP BY 
 fiscal_year;

在这两个例子中,聚合函数都减少了查询返回的行数。

像带有GROUP BY子句的聚合函数一样,窗口函数也对一部分行进行操作,但它们不会减少查询返回的行数。

例如,以下查询返回每个员工的销售额,以及员工按财年的总销售额:

SELECT 
 fiscal_year, 
 sales_employee,
 sale,
 SUM(sale) OVER (PARTITION BY fiscal_year) total_sales
FROM
 sales;

在这个例子中,SUM()函数作为一个窗口函数,操作由OVER子句内容定义的一组行。SUM()函数应用的一组行被称为窗口。

SUM()窗口函数不仅报告了按财年的总销售额(就像在带有GROUP BY子句的查询中那样),而且还在每一行中报告了结果,而不是返回的总行数。

注意,窗口函数是在所有JOIN、WHERE、GROUP BY和HAVING子句之后,以及在ORDER BY、LIMIT和SELECT DISTINCT之前执行的。

窗口函数的语法如下:

window_function_name(expression) OVER ( 
 [partition_defintion]
 [order_definition]
 [frame_definition]
) 

在这个语法中:

首先,指定窗口函数名称,后面跟着一个表达式。

其次,指定OVER子句,它有三个可能的元素:分区定义、排序定义和帧定义。

在OVER子句后面的开括号和闭括号是必需的,即使没有表达式,例如:

window_function_name(expression) OVER()

在本教程中,你已经了解了MySQL窗口函数及其语法。