MySQL聚合窗口函数实战指南

mysql聚合窗口函数用法

时间:2025-06-21 08:29


MySQL聚合窗口函数用法详解 在数据分析和处理的场景中,MySQL的聚合窗口函数提供了一种强大且灵活的工具,能够在不改变原始数据行数的前提下,执行复杂的跨行计算

    本文将详细介绍MySQL聚合窗口函数的用法,并通过实例展示其在实际应用中的强大功能

     一、窗口函数的基本概念 窗口函数(Window Functions)是SQL标准的一部分,它们通过在查询结果集上定义一个“窗口”来工作

    这个窗口可以是整个结果集,也可以是结果集的一个子集

    窗口函数会对窗口内的行执行计算,并为每一行返回一个值

    这个值是根据窗口内行的值以及窗口函数本身的逻辑计算得出的

     窗口函数不会改变查询结果集的行数,而是为每一行添加一个额外的列,这个列包含了窗口函数的计算结果

    这使得窗口函数非常适合于需要在保持原始数据的同时进行聚合或其他复杂计算的场景

     二、聚合窗口函数的语法结构 MySQL的聚合窗口函数的基本语法结构如下: sql <窗口函数(<参数) OVER(【PARTITION BY <分区表达式>】【ORDER BY <排序表达式>【ASC | DESC】】【ROWS/RANGE <窗口范围>】) -`<窗口函数(<参数)`:指定要使用的窗口函数及其参数

    窗口函数可以是聚合函数(如SUM、AVG等),也可以是专门为窗口函数设计的函数(如ROW_NUMBER、RANK等)

     -`OVER()`:定义窗口的框架

    所有窗口函数都需要使用`OVER()`子句来指定窗口的范围和行为

     -`PARTITION BY <分区表达式`(可选):将结果集分成多个分区,窗口函数会在每个分区内独立执行

    分区表达式可以是一个或多个列名,用于确定如何将结果集分成不同的分区

     -`ORDER BY <排序表达式>【ASC | DESC】`(可选):指定窗口内行的排序顺序

    排序表达式可以是一个或多个列名,用于确定窗口内行的排序方式

     -`ROWS/RANGE <窗口范围`(可选):定义窗口的行范围

    行范围可以是固定的行数(如ROWS BETWEEN2 PRECEDING AND CURRENT ROW),也可以是相对于当前行的动态范围(如ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW,表示从窗口开始到当前行的所有行)

     三、常见的聚合窗口函数 1.SUM():计算窗口内某列的总和

     2.AVG():计算窗口内某列的平均值

     3.COUNT():计算窗口内的行数

     4.MIN():获取窗口内某列的最小值

     5.MAX():获取窗口内某列的最大值

     四、排名窗口函数 除了聚合函数外,MySQL还提供了一些专门为窗口函数设计的函数,如排名函数: 1.ROW_NUMBER():为窗口内的每一行分配一个唯一的行号

     2.RANK():为窗口内的每一行分配一个排名,如果排名相同,则跳过后续排名(如1、2、2、4)

     3.DENSE_RANK():为窗口内的每一行分配一个排名,如果排名相同,则不跳过后续排名(如1、2、2、3)

     4.NTILE(n):将窗口内的行均匀划分为n个组,并为每一行分配一个组号

     五、跨行取值窗口函数 跨行取值函数允许我们在窗口内访问当前行之前或之后的行的值: 1.LAG(列, 偏移, 默认值):返回当前行之前指定偏移量的行的值

    如果未指定偏移量,则默认为1(即上一行)

    如果指定了默认值,则在无法获取指定行的值时返回该默认值

     2.LEAD(列, 偏移, 默认值):返回当前行之后指定偏移量的行的值

    其余参数与LAG函数相同

     3.FIRST_VALUE(列):返回窗口内第一行的值

     4.LAST_VALUE(列):返回窗口内最后一行的值

     六、窗口范围关键字 在定义窗口范围时,MySQL提供了几个关键字来控制窗口的起始和结束位置: -UNBOUNDED PRECEDING:窗口从当前分区的第一行开始

     -N PRECEDING:窗口从当前行之前的第N行开始

     -CURRENT ROW:窗口从当前行开始

     -N FOLLOWING:窗口从当前行之后的第N行开始

     -UNBOUNDED FOLLOWING:窗口到当前分区的最后一行结束

     七、实例展示 1.计算每个部门的工资总和及平均值 sql SELECT dname, ename, salary, SUM(salary) OVER(PARTITION BY dname) AS dept_salary_sum, AVG(salary) OVER(PARTITION BY dname) AS dept_salary_avg FROM employees; 此查询为每个部门的员工计算了工资总和及平均值,同时保留了每条记录

     2.计算每个员工的工资排名 sql SELECT employee_id, department, salary, RANK() OVER(PARTITION BY department ORDER BY salary DESC) AS dept_rank FROM employees; 此查询为每个部门内的员工按工资从高到低进行了排名

     3.计算每个员工相对于部门的工资环比 sql SELECT employee_id, department_id, salary, salary - LAG(salary) OVER(PARTITION BY department_id ORDER BY salary) AS salary_diff FROM employees; 此查询计算了每个员工相对于其所在部门的前一个员工的工资差额

    注意,这里的排序是基于salary列进行的,但在实际应用中,可能需要根据实际业务需求选择合适的排序列

     4.使用ROWS和RANGE指定窗口范围 sql -- 使用ROWS指定窗口范围,计算当前行及其前两行的销售额总和 SELECT sale_date, amount, SUM(amount) OVER(ORDER BY sale_date ROWS BETWEEN2 PRECEDING AND CURRENT ROW) AS rolling_total FROM sales; -- 使用RANGE指定窗口范围,计算当前行值附近范围内的平均值 SELECT price, AVG(price) OVER(ORDER BY price RANGE BETWEEN10 PRECEDING AND10 FOLLOWING) AS avg_nearby_price FROM products; 第一个查询计算了包括当前行在内的前三行的销售额总和,而第二个查询则计算了当前价格值前后10个单位范围内的平均价格

     八、性能与场景对比 在大量数据场景下,窗口函数通常具有更优的性能和更简洁的语法结构,尤其在不需要将数据折叠时效果更佳

    与聚合函数相比,窗口函数支持更复杂的数据分析需求,同时能够保持原始数据的行数不变

    这使得窗口函数在数据分析和报告生成等场景中具有广泛的应用价值

     九、总结 MySQL的聚合窗口函数提供了一种强大且灵活的工具,能够在不改变原始数据行数的前