在日常的数据分析工作中,我们经常需要对数据进行分组排序、计算移动平均值、统计累计求和等操作。在MySQL 8.0之前,这类需求通常需要编写复杂的子查询或连接查询才能实现。而MySQL 8.0引入的窗口函数(Window Functions)极大地简化了这类操作,让数据分析变得更加简单高效。

        本文将通过通俗易懂的方式,带你全面了解MySQL 8.0中的窗口函数,包括聚合类、排名类和跨行类窗口函数的使用方法。

什么是窗口函数?

        窗口函数是一种特殊的SQL函数,它能够在不改变原有行数的情况下,对查询结果的某个"窗口"(一组相关的行)进行计算,并为每一行返回一个值。

        可以把窗口函数想象成:你有一张全班学生的成绩表,窗口函数允许你同时看到每个学生的成绩、他在班级中的排名、他与前一名同学的分数差等信息,而不需要改变原始数据表的行数。这个排名是新加的一行。

窗口函数的基本语法

SELECT 列1, 列2,窗口函数() OVER ([PARTITION BY 分区字段] [ORDER BY 排序字段][frame_clause]) AS 别名
FROM 表名;
  • PARTITION BY:将数据分成多个分区(类似于GROUP BY,但不合并行)

  • ORDER BY:确定分区内数据的排序方式

  • frame_clause:定义窗口框架,即计算范围

一、聚合类窗口函数

聚合类窗口函数可以在保留所有行的同时,计算分组的聚合值。

1. SUM() OVER()

计算分区内的总和:

-- 计算每个部门的工资总额,同时显示每个员工的详细信息
SELECT employee_id,name,department,salary,SUM(salary) OVER (PARTITION BY department) AS dept_total_salary
FROM employees;

2. AVG() OVER()

计算分区内的平均值:

-- 计算每个部门的平均工资,同时显示每个员工的详细信息
SELECT employee_id,name,department,salary,AVG(salary) OVER (PARTITION BY department) AS dept_avg_salary
FROM employees;

3. COUNT() OVER()

计算分区内的行数:

-- 计算每个部门的员工数量,同时显示每个员工的详细信息
SELECT employee_id,name,department,salary,COUNT(*) OVER (PARTITION BY department) AS dept_employee_count
FROM employees;

二、排名类窗口函数

排名类窗口函数用于为分区内的行分配排名、序号等。

1. ROW_NUMBER()

为分区内的每一行分配一个唯一的序号:1,2,3,4,5,6,7

-- 为每个部门的员工按工资从高到低编号
SELECT employee_id,name,department,salary,ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) as rank_in_dept
FROM employees;

2. RANK()

计算分区内的排名,相同值会有相同排名,并跳过后续排名:1,1,3,3,5,6,7

-- 计算每个部门内的工资排名(允许并列)
SELECT employee_id,name,department,salary,RANK() OVER (PARTITION BY department ORDER BY salary DESC) as salary_rank
FROM employees;

3. DENSE_RANK()

计算分区内的排名,相同值有相同排名,但不跳过后续排名:1,1,2,2,3,4,5,6,6

-- 计算每个部门内的工资密集排名(允许并列但不跳号)
SELECT employee_id,name,department,salary,DENSE_RANK() OVER (PARTITION BY department ORDER BY salary DESC) as dense_rank
FROM employees;

4. NTILE()

将分区内的数据分成指定数量的组:

-- 将每个部门的员工按工资高低分成4个组
SELECT employee_id,name,department,salary,NTILE(4) OVER (PARTITION BY department ORDER BY salary DESC) as quartile
FROM employees;

三、跨行类窗口函数

跨行类窗口函数可以访问分区内其他行的数据。

1. LAG()

访问分区中当前行之前的数据:

-- 查看每位员工和上一名员工的工资差异
SELECT employee_id,name,department,salary,LAG(salary) OVER (PARTITION BY department ORDER BY salary DESC) as prev_salary,salary - LAG(salary) OVER (PARTITION BY department ORDER BY salary DESC) as diff_from_prev
FROM employees;

2. LEAD()

访问分区中当前行之后的数据:

-- 查看每位员工和下一名员工的工资差异
SELECT employee_id,name,department,salary,LEAD(salary) OVER (PARTITION BY department ORDER BY salary DESC) as next_salary,salary - LEAD(salary) OVER (PARTITION BY department ORDER BY salary DESC) as diff_from_next
FROM employees;

3. FIRST_VALUE()

获取分区内第一行的值:

-- 查看每位员工与部门最高工资的差异
SELECT employee_id,name,department,salary,FIRST_VALUE(salary) OVER (PARTITION BY department ORDER BY salary DESC) as highest_salary,salary - FIRST_VALUE(salary) OVER (PARTITION BY department ORDER BY salary DESC) as diff_from_highest
FROM employees;

4. LAST_VALUE()

获取分区内最后一行的值:

-- 查看每位员工与部门最低工资的差异
SELECT employee_id,name,department,salary,LAST_VALUE(salary) OVER (PARTITION BY department ORDER BY salary DESCRANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as lowest_salary,salary - LAST_VALUE(salary) OVER (PARTITION BY department ORDER BY salary DESCRANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as diff_from_lowest
FROM employees;

注意:使用LAST_VALUE()时需要特别注意窗口框架的定义,否则可能得不到预期结果。

窗口框架(Window Frame)详解

窗口框架定义了窗口函数计算时使用的行范围,常用的有两种:

  1. ROWS模式:基于物理行偏移

  2. RANGE模式:基于逻辑值偏移

示例:计算移动平均值

-- 计算每个员工与前2行、当前行、后2行共5行的平均工资
SELECT employee_id,name,department,salary,AVG(salary) OVER (PARTITION BY department ORDER BY salary DESCROWS BETWEEN 2 PRECEDING AND 2 FOLLOWING) as moving_avg
FROM employees;

实际应用场景

场景1:计算同比/环比增长率

-- 计算每月销售额与上月相比的增长率
SELECT year,month,sales,LAG(sales) OVER (ORDER BY year, month) as prev_month_sales,(sales - LAG(sales) OVER (ORDER BY year, month)) / LAG(sales) OVER (ORDER BY year, month) * 100 as growth_rate
FROM monthly_sales;

场景2:获取Top N记录

-- 获取每个部门工资前三名的员工
WITH ranked_employees AS (SELECT employee_id,name,department,salary,DENSE_RANK() OVER (PARTITION BY department ORDER BY salary DESC) as rank_in_deptFROM employees
)
SELECT * FROM ranked_employees WHERE rank_in_dept <= 3;

场景3:计算累计百分比

-- 计算每个部门工资的累计百分比
SELECT employee_id,name,department,salary,SUM(salary) OVER (PARTITION BY department ORDER BY salary DESC) as running_total,SUM(salary) OVER (PARTITION BY department) as dept_total,SUM(salary) OVER (PARTITION BY department ORDER BY salary DESC) / SUM(salary) OVER (PARTITION BY department) * 100 as cumulative_percent
FROM employees;

性能优化建议

  1. 合理使用索引:为PARTITION BY和ORDER BY涉及的字段创建索引

  2. 避免过度使用窗口函数:在数据量大的表中,窗口函数可能影响性能

  3. 使用CTE(公用表表达式):将复杂查询分解为多个步骤,提高可读性和性能

  4. 限制窗口大小:对于移动平均等计算,尽量限制窗口框架的范围

总结

MySQL 8.0的窗口函数为数据分析提供了强大而灵活的工具,使我们能够在保留原始行细节的同时,进行各种复杂的计算和分析。通过本文的学习,你应该已经掌握了:

  1. 窗口函数的基本概念和语法结构

  2. 聚合类、排名类和跨行类窗口函数的使用方法

  3. 窗口框架的定义和使用场景

  4. 窗口函数在实际业务中的应用示例

窗口函数的学习曲线可能稍陡,但一旦掌握,将极大地提升你的数据处理能力和工作效率。建议在实际工作中多加练习,逐步掌握这些强大的功能。

希望本文对你理解和使用MySQL 8.0窗口函数有所帮助!如有任何疑问,欢迎留言讨论。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/97762.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/97762.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/97762.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【论文阅读】DeepSeek-LV2:用于高级多模态理解的专家混合视觉语言模型

【论文阅读】DeepSeek-LV2&#xff1a;用于高级多模态理解的专家混合视觉语言模型 文章目录【论文阅读】DeepSeek-LV2&#xff1a;用于高级多模态理解的专家混合视觉语言模型一、介绍二、模型结构三、数据建设**3.1 对齐****3.2 视觉语言预训练数据****3.3 监督微调数据**四、训…

一款为开发者而生的开源全栈LLMOps平台

&#x1f680; 超越ChatGPT&#xff01;一款为开发者而生的全栈LLMOps平台&#xff1a;LMForge完全指南 作为一名AI应用开发者&#xff0c;你是否也曾遇到过这些令人头疼的问题&#xff1f; 成本失控&#xff1a;GPT-4的API账单像雪片一样飞来&#xff0c;却不知道钱具体花在…

DeepL Translate在线工具测评:精准翻译技术文档与学术论文,支持多格式文档上传保留原格式

之前跟你们聊过帮着梳理代码协作的 GitLens&#xff0c;今天换个偏向文档翻译的方向 —— 给你们安利一个在线 AI 翻译工具「DeepL Translate」&#xff0c;官网地址是DeepL Translate: The worlds most accurate translator&#xff0c;它跟普通翻译工具不一样&#xff0c;翻技…

系统配置不是“乐高积木”:制造企业如何通过科学变更管理保障稳定运行

在制造业的数字化进程中&#xff0c;系统配置的稳定性常被忽视。作为一家制造企业的行政经理&#xff0c;我曾亲历这样的场景&#xff1a;为应对生产波动&#xff0c;各部门频繁要求调整ERP系统参数&#xff0c;结果导致库存数据失真、订单处理延迟&#xff0c;甚至引发客户投诉…

vscode炒股插件-韭菜盒子AI版

基于vscode插件&#xff0c;原韭菜盒子3.15.0版本开发&#xff0c;新增选股宝快讯功能、AI投资助手、指定股票AI分析功能&#xff08;目前只针对A股&#xff09;&#xff0c;内置AI大模型助手功能&#xff0c;支持ai分析最新资讯、ai分析当日资讯&#xff08;让ai随时给你分析股…

Spring Cloud Config 核心原理

Spring Cloud Config 是 Spring Cloud 提供的一个用于集中化管理应用程序各个环境下的配置属性的解决方案。它支持统一管理配置&#xff0c;并且可以在不重启应用的情况下动态地更新配置信息&#xff0c;提高开发和运维效率。 主要特点 • 集中管理配置&#xff1a;可以将不同环…

springboot ioc 控制反转入门与实战

Spring Boot3 IOC 项目地址https://gitee.com/supervol/loong-springboot-study&#xff08;记得给个start&#xff0c;感谢&#xff09;IOC 概述在 Spring Boot 3 中&#xff0c;IOC&#xff08;Inversion of Control&#xff0c;控制反转&#xff09;是核心思想之一&#xff…

LangGraph 重要注意事项和常见问题

01. 数据状态与归纳函数在前面的课时中&#xff0c;我们说过在 LangGraph 中 节点 在默认情况下返回的字典数据会将原始数据覆盖&#xff0c;例如下面的代码最终返回结果是 {"messages": [4]} 而不是 [1,2,3,4]&#xff0c;如下class MyState(TypedDict):messages: l…

避坑指南!解决Navicat运行SQL成功但没有表的问题

在运行转储的SQL文件时&#xff0c;成功运行&#xff0c;试了很多办法都不显示出表。原因&#xff1a;当从一个高版本的 MySQL 数据库导入数据到低版本的 MySQL 数据库时&#xff0c;可能会遇到兼容性问题。因为高版本的 MySQL 可能支持 utf8mb4_0900_ai_ci&#xff0c;而低版本…

在 Elasticsearch 中使用用户行为分析:使用 UBI 和 search-ui 创建一个应用程序

作者&#xff1a;来自 Elastic Eduard Martin 及 Alexander Dvila 通过一个实际示例学习如何在 Elasticsearch 中使用 UBI。我们将创建一个在搜索和点击结果时生成 UBI 事件的应用程序。 想要获得 Elastic 认证吗&#xff1f;看看下一次 Elasticsearch Engineer 培训什么时候开…

SpringBoot3中使用Caffeine缓存组件

SpringBoot3已经把EhCache从框架中删除了&#xff0c;SpringBoot3默认的缓存组件为Caffeine&#xff0c;那么我们在SpringBoot3中如何去使用它了&#xff1f; 1.添加依赖 <dependency><groupId>com.github.ben-manes.caffeine</groupId><artifactId>ca…

正则表达式与grep文本过滤详解

文章目录前言一、正则表达式概述1.1 定义1.2 主要用途1.3 Linux 中的正则表达式分类1.3.1 基础正则表达式&#xff08;BRE&#xff09;1.3.2 扩展正则表达式&#xff08;ERE&#xff09;二、正则表达式的基本组成2.1 普通字符2.2 元字符2.2.1 基本元字符2.2.2 重复次数相关2.2.…

Dify 集成 Milvus 配置指南

&#x1f9e9; Dify 集成 Milvus 配置指南 &#x1f527; 详细配置步骤 1. 环境准备与克隆仓库 首先确保你的系统已安装 Git、Docker 和 Docker Compose。然后克隆 Dify 的代码仓库&#xff1a; git clone https://github.com/langgenius/dify.git cd dify/docker2. 配置环境变…

为不平,不止于此

口碑可以成就一个人&#xff0c;也可以毁掉一个人&#xff0c; 所以我们选择用实力去创造两种无声的口碑。 要么让期待的你张口而呼&#xff0c; 要么让挑剔的你哑口无言。玛哈特科技创始人 #为不平&#xff0c;不止于此#

0902 C++类的匿名对象

Part 1.梳理思维导图一.匿名对象1.概念没有对象名的类对象2.格式类名();3.作用1.给有名对象初始化2.给对象数组初始化3.作为函数的参数传递给形参4.例子#include <iostream>using namespace std;class Dog {friend void Dogfriend(Dog &b); private:string name;int …

在 PySpark 中解锁窗口函数的力量,实现高级数据转换

本篇文章Mastering PySpark Window Functions: A Practical Guide to Time-Based Analytics适合数据分析和工程师入门了解PySpark的窗口函数。文章的亮点在于详细介绍了窗口函数的基本概念及其在销售数据分析中的实际应用&#xff0c;帮助读者理解如何进行复杂的数据计算而无需…

从理念到实践:三层解耦架构与“无系统”论

在上一篇中&#xff0c;我们揭示了“五层双闭环”治理模型如何像骨骼一样&#xff0c;为数字化转型提供支撑和定型。但再宏伟的蓝图也需要坚实的施工来实现。今天&#xff0c;我们将深入最具体的实施层面&#xff0c;将“业务重塑”和“以人为本”的理念&#xff0c;转化为可落…

详细介绍Linux 内存管理struct page数据结构中的_count和_mapcount有什么区别?

在Linux内核的struct page中&#xff0c;_count&#xff08;或_refcount&#xff09;和_mapcount是两个关键的引用计数成员&#xff0c;它们各自承担不同的职责。以下是深度解析和代码案例&#xff1a;1. _count vs _mapcount 区别详解_count&#xff08;或_refcount&#xff0…

面阵 vs 线阵相机:怎么选不踩坑?选型公式直接套用

面阵vs线阵相机&#xff1a;怎么选不踩坑&#xff1f;选型公式直接套用&#x1f3af;面阵vs线阵相机怎么选不踩坑&#xff1f;&#x1f3af;一、面阵相机&#xff1a;工业检测的“万能选手”&#xff0c;拍全图靠它&#x1f3af;二、线阵相机&#xff1a;大视野/高精度的“专属…

Spring Security 如何使用@PreAuthorize注解

&#x1f9f1; 第一步&#xff1a;环境准备✅ 1. 创建数据库&#xff08;MySQL&#xff09;-- 创建数据库&#xff0c;使用 utf8mb4 字符集支持 emoji 和多语言 CREATE DATABASE security_demo CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;-- 使用该数据库 USE security…