前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >MySQL8 窗口函数

MySQL8 窗口函数

作者头像
程序猿川子
发布于 2024-11-08 03:46:00
发布于 2024-11-08 03:46:00
20000
代码可运行
举报
运行总次数:0
代码可运行

MySQL8 还是有很多重量级变化的,一些底层优化大家在使用中有时候不易察觉,但是有一些用法,还是带给我们耳目一新的感觉,今天松哥和大家分享一下 MySQL8 里边的窗口函数。

一 什么是窗口函数

MySQL 8 中,窗口函数(Window Functions)是一类强大的分析函数,允许你在查询结果集上执行计算,而无需将数据分组到多个输出行中。窗口函数通常与 OVER() 子句一起使用,以指定数据窗口,即窗口函数将要在其上执行计算的行集。

简单来说,窗口函数的作用类似于在查询中对数据进行分组,不同的是,分组操作会把分组的结果聚合成一条记录,而窗口函数是将结果置于每一条数据记录中。

窗口函数的格式类似下面这样:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
sql 代码解读复制代码<窗口函数> OVER ([PARTITION BY <分组列> [, <分组列>...]]
                     [ORDER BY <排序列> [ASC | DESC] [, <排序列> [ASC | DESC]]...]
                     [<rows or range clause>])
  • <窗口函数> : 定义要在窗口中计算的聚合函数或其它分析函数,如 COUNTRANKSUM 等。
  • OVER : 窗口函数的核心关键字。
  • PARTITION BY : 定义要用来分组的一组列名。
  • ORDER BY : 定义用来排序的一组列名。
  • <rows or range clause> : 定义窗口的行集合。默认为 ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW,表示窗口包括从窗口开始到当前行的所有行。

接下来我们通过一个实际案例来体会下窗口函数。

二 窗口函数实践

2.1 统计成绩和排名

假设我有如下一张表:

我现在想要计算学生的考试总成绩以及单科成绩排名,利用窗口函数就能快速搞定,如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
sql 代码解读复制代码SELECT name,subject,score,
SUM(score) OVER(PARTITION by name) AS '总分',
DENSE_RANK() OVER(PARTITION by subject ORDER BY score DESC) AS '学科排名'
from student

和窗口函数相关的就两列:

  • sum 求总分,over 中按照 name 进行分组,相当于就是计算每个人的总分。
  • dense_rank 是排序,这个函数会考虑并列的情况,但是并列并不影响排序,因为是计算每个人单科排名,所以就按照学科分组之后按照 score 排序。

最终执行结果如下:

2.2 销售统计

假设我有如下一张表:

这是一个名为 sales 的表,其中包含 id(销售记录 ID)、product_id(产品 ID)、sale_date(销售日期)和 amount(销售额)等字段。

现在有如下几个需求,大家把这几个需求搞懂了,基本上窗口函数就会用了。

计算累计销售额

需求:按产品 ID 分组,计算每个产品的累计销售额。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
sql 代码解读复制代码SELECT 
    id, 
    product_id, 
    sale_date, 
    amount, 
    SUM(amount) OVER (PARTITION BY product_id ORDER BY sale_date) AS '累计销售额'
FROM 
    sales;

SUM(amount) OVER (PARTITION BY product_id ORDER BY sale_date) AS '累计销售额' 表示按 product_id 分组,按 sale_date 排序,计算每个产品的累计销售额。

最终查询结果如下:

计算移动平均值

需求:按产品 ID 分组,计算每个产品的最近 3 笔销售记录的移动平均销售额。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
sql 代码解读复制代码SELECT 
    id, 
    product_id, 
    sale_date, 
    amount, 
    AVG(amount) OVER (PARTITION BY product_id ORDER BY sale_date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS '移动平均销售额'
FROM 
    sales;

AVG(amount) OVER (PARTITION BY product_id ORDER BY sale_date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS '移动平均销售额' 表示按 product_id 分组,按 sale_date 排序,计算当前行及前两行的平均销售额。

最终查询结果如下:

计算排名

需求:按产品 ID 分组,计算每个销售记录在该产品中的排名。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
sql 代码解读复制代码SELECT 
    id, 
    product_id, 
    sale_date, 
    amount, 
    RANK() OVER (PARTITION BY product_id ORDER BY amount DESC) AS '销售金额排名'
FROM 
    sales;

RANK() OVER (PARTITION BY product_id ORDER BY amount DESC) AS '销售金额排名' 表示按 product_id 分组,按 amount 降序排序,计算每个销售记录在该产品中的排名。

最终查询结果如下:

计算百分比排名

需求:按产品 ID 分组,计算每个销售记录在该产品中的百分比排名。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
sql 代码解读复制代码SELECT 
    id, 
    product_id, 
    sale_date, 
    amount, 
    PERCENT_RANK() OVER (PARTITION BY product_id ORDER BY amount DESC) AS '百分比排名'
FROM 
    sales;

PERCENT_RANK() OVER (PARTITION BY product_id ORDER BY amount DESC) AS '百分比排名' 表示按 product_id 分组,按 amount 降序排序,计算每个销售记录在该产品中的百分比排名。

最终查询结果如下:

计算前后行的差值

需求:按产品 ID 分组,计算每个销售记录与上一个销售记录之间的销售额差值。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
sql 代码解读复制代码SELECT 
    id, 
    product_id, 
    sale_date, 
    amount, 
    LAG(amount, 1) OVER (PARTITION BY product_id ORDER BY sale_date) AS '上个销售记录',
    amount - LAG(amount, 1) OVER (PARTITION BY product_id ORDER BY sale_date) AS '差额'
FROM 
    sales;

LAG(amount, 1) OVER (PARTITION BY product_id ORDER BY sale_date):按 product_id 分组,按 sale_date 排序,获取当前行的上一行的 amount 值。 amount - LAG(amount, 1) OVER (PARTITION BY product_id ORDER BY sale_date):计算当前行与上一行的销售额差值。

最终查询结果如下:

计算第一个和最后一个值

需求:按产品 ID 分组,计算每个产品的第一个和最后一个销售日期。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
sql 代码解读复制代码SELECT 
    product_id, 
    MIN(sale_date) OVER (PARTITION BY product_id) AS '第一个销售日期', 
    MAX(sale_date) OVER (PARTITION BY product_id) AS '最后一个销售日期'
FROM 
    sales;

MIN(sale_date) OVER (PARTITION BY product_id):按product_id分组,计算每个产品的第一个销售日期。 MAX(sale_date) OVER (PARTITION BY product_id):按product_id分组,计算每个产品的最后一个销售日期。

最终查询结果如下:

好啦,通过这几个小小案例,小伙伴们明白窗口函数了吧~

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Java NIO Selector 详解
Selector 允许一个单一的线程来操作多个 Channel,如果我们的应用程序中使用了多个 Channel,那么使用 Selector 很方便的实现这样的目的,但是因为在一个线程中使用了多个 Channel,因此也会造成了每个 Channel 传输效率的降低。
玄姐谈AGI
2020/09/29
1.6K0
Java NIO Selector 详解
Java中的NIO基础知识
上一篇介绍了五种NIO模型,本篇将介绍Java中的NIO类库,为学习netty做好铺垫
Janti
2018/08/01
5520
Java中的NIO基础知识
NIO系列(二)——Channel通道复制和Selector选择器
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
逝兮诚
2019/10/30
4540
012. NIO 非阻塞网络编程
1. Java NIO ---- 始于 Java1.4,提供了新的 JAVA IO 操作非阻塞 API。用意是替代 Java IO 和 Java Networking 相关的 API。 三个核心组件 Buffer 缓冲区 Channel 通道 Selector 选择器 2. Buffer 缓冲区 ---- 1. 介绍 缓冲区本质上是一个可以写入数据的内存块(类似数组),然后可以再次读取。此内存块包含在 NIO Buffer 对象中,该对象提供了一组方法,可以更轻松地使用内存块。 相比较直接对数组的操
山海散人
2021/03/03
4100
012. NIO 非阻塞网络编程
Java NIO Selector 使用
之前的文章已经把 Java 中 NIO 的 Buffer、Channel 讲解完了,不太了解的可以先回过头去看看。这篇文章我们就来聊聊 Selector —— 选择器。
SH的全栈笔记
2022/08/17
3380
Java NIO Selector 使用
Java网络编程与NIO详解4:浅析NIO包中的Buffer、Channel 和 Selector
本系列文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看
Java技术江湖
2019/11/21
4700
NIO 和 IO 到底有什么区别?别说你不会!
通道是对原 I/O 包中的流的模拟。到任何目的地(或来自任何地方)的所有数据都必须通过一个 Channel 对象(通道)。
Java技术栈
2020/03/17
1.3K0
NIO 和 IO 到底有什么区别?别说你不会!
JavaIO流:NIO梳理
NIO 也叫 Non-Blocking IO 是同步非阻塞的 IO 模型。线程发起 IO 请求后,立即返回。同步指的是必须等待 IO 缓冲区内的数据就绪,而非阻塞指的是,用户线程不原地等待 IO 缓冲区,可以先做一些其他操作,但是要定时轮询检查 IO 缓冲区数据是否就绪。
栗筝i
2022/12/02
3280
JavaIO流:NIO梳理
Java NIO、Channel、Selector 详解
Buffer 是一个特定原始类型的容器。Buffer 是一个原始类型的线性的、有限序列,除了 Buffer 存储的内容外,关键属性还包括:capacity, limit 和 position。
Yano_nankai
2019/11/10
1.2K0
Java NIO、Channel、Selector 详解
Netty: NIO Selector选择器(C/S demo详细注释与源码)
三个元素: Selector选择器、SelectableChannel可选择的通道、SelectionKey选择键
冷环渊
2021/11/17
2800
Netty: NIO Selector选择器(C/S demo详细注释与源码)
Java NIO 核心组件学习笔记
对于I/O操作,根据Oracle官网的文档,同步异步的划分标准是“调用者是否需要等待I/O操作完成”,这个“等待I/O操作完成”的意思不是指一定要读取到数据或者说写入所有数据,而是指真正进行I/O操作时,比如数据在TCP/IP协议栈缓冲区和JVM缓冲区之间传输的这段时间,调用者是否要等待。
Java团长
2018/08/07
4620
java nio
文章目录 1. 缓冲区(Buffer) 1.1. 常用的方法 1.2. 核心属性 1.3. 直接缓冲区 1.4. 非直接缓冲区 2. 通道(Channel) 2.1. 获取通道 2.2. 实例 2.3. 通道之间指定进行数据传输 2.4. 分散读取 2.5. 聚集写入 2.6. NIO阻塞式 3. Selector(选择器) 3.1. SelectionKey 3.2. NIO非阻塞式 4. 参考文章 缓冲区(Buffer) 负责数据的存取,实际上就是一个数组,用于存储不同的数据 除了布尔类型之后,其他
爱撒谎的男孩
2019/12/31
1.1K0
NIO详解
NIO (New lO)也有人称之为java non-blocking lO是从Java 1.4版本开始引入的一个新的IO API,可以替代标准的Java lO API。
冬天vs不冷
2025/01/21
1900
NIO详解
【Netty】NIO 网络通信 SelectionKey 常用 API 简介
1 . 通道注册给选择器 : 通道 ( Channel ) 注册给 选择器 ( Selector ) , 该通道就会纳入到该 选择器 ( Selector ) 管理范畴 , 选择器 ( Selector ) 可以监听通道的事件 ;
韩曙亮
2023/03/27
3580
Netty-nio
channel 有一点类似于 stream,它就是读写数据的双向通道,可以从 channel 将数据读入 buffer,也可以将 buffer 的数据写入 channel,而之前的 stream 要么是输入,要么是输出,channel 比 stream 更为底层
sgr997
2022/11/10
7180
Netty-nio
NIO全解析说明
Java NIO是一个用来替代标准Java IO API的新型数据传递方式,像现在分布式架构中会经常存在他的身影。其比传统的IO更加高效,非阻塞,异步,双向
迹_Jason
2019/05/30
8210
Java NIO?看这一篇就够了!
✎前言 现在使用NIO的场景越来越多,很多网上的技术框架或多或少的使用NIO技术,譬如Tomcat,Jetty。学习和掌握NIO技术已经不是一个JAVA攻城狮的加分技能,而是一个必备技能。在前面2篇文
方志朋
2019/06/21
1.1K0
Java NIO?看这一篇就够了!
🎯 Java NIO 基础
✏️ 写在前面的话: Netty本质是一个NIO框架,适用于服务器通讯相关的多种应用场景。 Netty作为一款基于Java开发的高性能网络框架,想要从认识到熟悉再到掌握最终理解,因此我们需要从最基础的NIO开始学习。如果你已经学习并掌握了NIO相关知识,那么可以直接进入Netty相关文章的学习;如果没有了解过也没有关系,那我们就从当前文章开始学习吧!🎉🎉🎉 这里我们先简单了解一下这一篇文章中我们将要学习的内容: 首先是NIO的基本介绍,了解NIO的三大组件 ByteBuffer 字节缓冲区的基本使用
爱吃糖的范同学
2023/02/11
8270
Java面试必问通信框架NIO,原理详解
新的输入/输出 (NIO) 库是在 JDK 1.4 中引入的,弥补了原来的 I/O 的不足,提供了高速的、面向块的 I/O。
李红
2019/05/31
1.3K0
Java面试必问通信框架NIO,原理详解
java的IO模型
本文主要是重新梳理了Java的IO模型,基于之前NIO的文章进行补充,为学习Netty做准备。
贪挽懒月
2020/07/14
7360
相关推荐
Java NIO Selector 详解
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验