从MySQL5到MySQL8,其中一个尤为显著的增强便是窗口函数的引入
这一功能不仅极大地丰富了MySQL的数据处理能力,还为数据分析师和开发者提供了更为高效和灵活的数据操作手段
本文将深入探讨MySQL窗口函数的原理、语法、常用函数及其实际应用场景,以帮助读者全面掌握这一强大的数据处理工具
一、窗口函数基础概念 窗口函数(Window Function),也称为分析函数(Analytic Function)或OLAP函数(OnLine Analytical Processing Function),是MySQL8.0及以上版本引入的一种功能强大的数据处理工具
它允许用户在不减少查询结果行数的情况下,对一组相关的行(称为“窗口”)执行计算
与传统的聚合函数(如SUM、AVG)不同,窗口函数不会将多行数据聚合为一行,而是为每一行数据返回一个计算结果
这些结果基于定义的“窗口”(即数据子集)进行计算,从而保留了原始数据的所有行,同时提供了组内计算的灵活性
窗口函数的基本语法结构如下: sql <窗口函数> OVER( 【PARTITION BY <分组列】 【ORDER BY <排序列】 【ROWS/RANGE BETWEEN <窗口起始位置> AND <窗口结束位置】 ) -窗口函数:可以是专用窗口函数(如ROW_NUMBER()、RANK()、DENSE_RANK()等),也可以是聚合函数(如SUM()、AVG()、COUNT()、MAX()、MIN()等)作为窗口函数使用
-OVER关键字:标志着窗口函数的开始,用于定义窗口的范围和计算规则
-PARTITION BY子句:指定分组依据,将数据划分为不同的组
窗口函数将在每个组内分别进行计算
如果省略该子句,则将整个结果集视为一个组
-ORDER BY子句:定义组内数据的排序顺序,影响窗口函数的计算逻辑
例如,在计算累计和时,数据的排序顺序决定了累加的顺序
-ROWS/RANGE子句:用于定义窗口的范围,即参与计算的数据行区间
UNBOUNDED PRECEDING表示从窗口起始行(第一行)开始,CURRENT ROW表示当前行,UNBOUNDED FOLLOWING表示到窗口结束行(最后一行)结束
也可以指定具体的偏移量,如ROWS BETWEEN1 PRECEDING AND1 FOLLOWING表示当前行及其前一行和后一行
二、常用窗口函数详解 1.排名函数 -ROW_NUMBER():为每一行数据生成一个唯一的连续序号,序号从1开始,按照ORDER BY指定的顺序依次递增
常用于分页查询、生成行号等场景
sql SELECT order_id, order_date, ROW_NUMBER() OVER(ORDER BY order_date) AS row_num FROM orders; -RANK():对数据进行排名,相同值的行具有相同的排名,但排名会出现跳跃
例如,若有两个第一名,则下一个排名为第三名
sql SELECT product_id, product_name, price, RANK() OVER(ORDER BY price DESC) AS price_rank FROM products; -DENSE_RANK():同样用于排名,但与RANK()不同的是,相同值的行具有相同的排名,且排名不会出现跳跃
sql SELECT employee_id, employee_name, salary, DENSE_RANK() OVER(ORDER BY salary DESC) AS salary_dense_rank FROM employees; -NTILE():桶排序函数,根据分组依据将每个组的总记录数按照指定的桶数进行均分,然后按照排序等级划分
常用于提取前百分之多少的应用场景
2.聚合窗口函数 -SUM():计算指定列在窗口范围内的累计和
sql SELECT order_date, order_amount, SUM(order_amount) OVER(ORDER BY order_date) AS cumulative_amount FROM orders; -AVG():计算窗口范围内指定列的平均值
sql SELECT product_id, month, sales_volume, AVG(sales_volume) OVER(PARTITION BY product_id ORDER BY month) AS avg_sales FROM product_sales; -COUNT():统计窗口范围内的行数
sql SELECT customer_id, order_date, COUNT(order_id) OVER(PARTITION BY customer_id ORDER BY order_date) AS order_count FROM orders; -MAX()和MIN():分别获取窗口范围内的最大值和最小值
sql SELECT department_id, employee_name, salary, MAX(salary) OVER(PARTITION BY department_id) AS max_salary_department, MIN(salary) OVER(PARTITION BY department_id) AS min_salary_department FROM employees; 3.偏移函数 -LAG():获取窗口内当前行的前n行的数据
它接受两个参数,第一个参数是要获取的列名,第二个参数是偏移量(默认为1)
sql SELECT order_id, order_date, order_amount, LAG(order_amount,1) OVER(ORDER BY order_date) AS prev_order_amount FROM orders; -LEAD():与LAG()函数相反,用于获取窗口内当前行的后n行的数据
同样接受两个参数,第一个参数是要获取的列名,第二个参数是偏移量(默认为1)
sql SELECT order_id, order_date, order_amount, LEAD(order_amount,1) OVER(ORDER BY order_date) AS next_order_amount FROM orders; 4.其他窗口函数 -FIRST_VALUE():取分组排序后的第一个值
-LAST_VALUE():取分组排序后的最后一个值(注意:在MySQL中可能不直接支持,但可通过其他方式实现类似效果)
三、窗口函数的应用场景 1.数据排名与筛选 窗口函数在