深入理解MySQL 8的窗口函数及其应用场景

引言:

MySQL 8的引入为数据库查询带来了一项强大的功能:窗口函数(Window Functions)。这些函数扩展了SQL的能力,允许开发者和数据分析师在保持数据行详情的同时执行高级统计和分析操作。

窗口函数概述:

窗口函数是一类特殊的SQL函数,它们在执行聚合计算时不会像GROUP BY子句那样折叠行,而是允许在定义的数据窗口上执行计算。这个"窗口"指的是一组排序后的行集合,通常是基于某些列的值进行分区。窗口函数可以访问窗口中的其他行而不仅仅是当前行,从而实现对数据的复杂分析。

使用示例

MySQL 8 引入了对窗口函数(Window Functions)的支持,这是一种强大的功能,用于执行数据的分区计算,而不需要将数据分组为单独的行。窗口函数可以对数据集的子集(称为窗口)执行聚合操作, 同时保持行的独立性。以下是一些常用的窗口函数及其使用示例:

  1. ROW_NUMBER(): 为每个分区内的行提供一个唯一的序号。

    sql 复制代码
    SELECT 
        name,
        department,
        salary,
        ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS row_num
    FROM employees;

这个查询会为每个部门内的员工根据薪水降序排列提供一个唯一的序号。

  1. RANK(): 在分区内对行进行排名,相同值的行会有相同的排名,排名之间会有间隔。

    sql 复制代码
    SELECT 
        name,
        department,
        salary,
        RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS rank
    FROM employees;
  2. DENSE_RANK(): 类似于RANK(),但排名之间不会有间隔。

    sql 复制代码
    SELECT 
        name,
        department,
        salary,
        DENSE_RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS dense_rank
    FROM employees;
  3. SUM(): 计算分区内值的总和。

    sql 复制代码
    SELECT 
        name,
        department,
        salary,
        SUM(salary) OVER (PARTITION BY department) AS department_total_salary
    FROM employees;
  4. AVG(): 计算分区内值的平均值。

    sql 复制代码
    SELECT 
        name,
        department,
        salary,
        AVG(salary) OVER (PARTITION BY department) AS department_avg_salary
    FROM employees;
  5. LEAD() 和 LAG(): 获取分区内当前行的下一行或上一行的值。

    sql 复制代码
    SELECT 
        name,
        department,
        salary,
        LEAD(salary) OVER (PARTITION BY department ORDER BY salary) AS next_highest_salary,
        LAG(salary) OVER (PARTITION BY department ORDER BY salary) AS previous_salary
    FROM employees;
  6. FIRST_VALUE() 和 LAST_VALUE(): 获取分区内的第一个值和最后一个值。

    sql 复制代码
    SELECT 
        name,
        department,
        salary,
        FIRST_VALUE(name) OVER (PARTITION BY department ORDER BY salary DESC) AS highest_earner,
        LAST_VALUE(name) OVER (PARTITION BY department ORDER BY salary DESC 
           RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS lowest_earner
    FROM employees;
  7. NTILE(): 将分区内的行分成指定数量的近似相等的排名组。

    sql 复制代码
    SELECT 
        name,
        department,
        salary,
        NTILE(4) OVER (PARTITION BY department ORDER BY salary DESC) AS quartile
    FROM employees;

在使用LAST_VALUE()函数时,通常需要指定窗口的范围,如示例中的RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING,以确保能够获取到整个分区内的最后一个值。

  1. CUME_DIST(): 计算当前行在其分区中的累积分布位置,其值为当前行之前的所有行数加上当前行(包含重复行)除以分区中的总行数。

    sql 复制代码
    SELECT 
        name,
        department,
        salary,
        CUME_DIST() OVER (PARTITION BY department ORDER BY salary DESC) AS cume_dist
    FROM employees;
  2. PERCENT_RANK(): 计算当前行的百分比排名,类似于RANK(),但表示为介于0和1之间的比例。

sql 复制代码
   SELECT 
       name,
       department,
       salary,
       PERCENT_RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS percent_rank
   FROM employees;

这些函数可以在各种数据分析任务中非常有用,例如计算累计总和、移动平均值或者进行排名。窗口函数的一个关键特征是它们允许在不改变原始数据集行数的情况下进行聚合计算。

业务场景应用:

窗口函数在多种业务场景中都有实际的应用价值:

  • 业绩评估: 通过RANK()DENSE_RANK(),可以快速识别出业绩最好或最差的员工。

  • 财务分析: SUM()AVG()窗口函数可以用来计算部门的总薪水或平均薪水,而不会丢失个别员工的薪水信息。

  • 数据挖掘: LEAD()LAG()函数可以用来比较序列数据,例如股票价格的前后变化。

  • 报告和分段: NTILE()可以用于分段用户或产品,以便进行更细致的市场分析。

结论:

MySQL 8的窗口函数为数据库查询提供了前所未有的灵活性和强大的分析能力。无论是数据分析师还是开发者,都可以利用这些工具来提升数据处理的效率和深度。掌握窗口函数的使用将是任何希望在数据驱动决策领域取得成功的专业人士的重要技能。

相关推荐
Pandaconda7 分钟前
【Golang 面试题】每日 3 题(三十九)
开发语言·经验分享·笔记·后端·面试·golang·go
编程小筑42 分钟前
R语言的编程范式
开发语言·后端·golang
技术的探险家1 小时前
Elixir语言的文件操作
开发语言·后端·golang
ss2731 小时前
【2025小年源码免费送】
前端·后端
Ai 编码助手1 小时前
Golang 中强大的重试机制,解决瞬态错误
开发语言·后端·golang
码农丁丁1 小时前
为什么数据库不应该使用外键
数据库·mysql·oracle·数据库设计·外键
齐雅彤2 小时前
Lisp语言的区块链
开发语言·后端·golang
齐雅彤2 小时前
Lisp语言的循环实现
开发语言·后端·golang
梁雨珈2 小时前
Lisp语言的物联网
开发语言·后端·golang
邓熙榆3 小时前
Logo语言的网络编程
开发语言·后端·golang