MySQL窗口函数(MySQL Window Functions)

news2024/12/24 2:12:07

1、窗口函数基本概念

官网地址:https://dev.mysql.com/doc/refman/8.0/en/window-functions.html

窗口可以理解为 记录集合,窗口函数就是在满足某种条件的记录集合上执行的特殊函数。
即:每条记录都要在此窗口内执行函数。

  • 静态窗口:每条记录都要在此窗口内执行函数,窗口大小都是固定的。

  • 动态窗口:不同的记录对应着不同的窗口,这种动态变化的窗口叫滑动窗口。

窗口函数也称为 OLAP(Online Anallytical Processing)函数,意思是对数据库数据进行实时分析处理。窗口函数就是为了实现 OLAP 而添加的标准 SQL 功能。

窗口函数对一组查询行执行类似聚合的操作。然而,聚合操作将查询行分组为单个结果行,而窗口函数为每个查询行生成一个结果:

  • 发生函数计算的行称为当前行。

  • 与对其进行函数计算的当前行相关的查询行构成当前行的窗口。

类似于这样下面这种
在这里插入图片描述

2、语法格式

函数名(字段名) over(子句);

over 括号内若不写,则意味着窗口函数基于满足 where 条件的所有行进行计算;
在这里插入图片描述

若括号内不为空,则支持以下语法来设置窗口:

函数名(字段名) over(partition by <要分列的组> order by <要排序的列> rows或者range  between <数据范围>) 
  • partition by子句:按照指定字段进行分区,两个分区由边界分隔,窗口函数在不同的分区内分别执行,在跨越分区边界时重新初始化。
  • order by子句:按照指定字段进行排序,窗口函数将按照排序后的记录顺序进行编号。可以和partition by子句配合使用,也可以单独使用。
  • frame子句:当前分区的一个子集,用来定义子集的规则,通常用来作为滑动窗口使用。

数据范围:

数据范围由units(单位)和 extent(范围) 两部分组成

单位可以有2种选择:

  • rows:通过起始行和结束行来划定范围,边界是明确的一行。
  • range:通过具有相同值的行来划定范围,边界是一个范围,具有相同值的行作为一个整体看待。

范围也要两种定义方式:

  • 只定义起始点(start),终止点(end)默认就是当前行。
  • 通过between start and end 子句,同时定义起始点(start)和终止点 (end)。

合法的startend可以有如下5种选择:

  1. current row:当单位是rows时,即当前行。当单位是range时,包含当前行和当前行相同的行(一个范围)。
  2. unbound preceding:窗口内第1行。
  3. unbound following:窗口内最后1行。
  4. expr preceding:当单位是rows时, 边界时当前行的前expr行。当单位是range时,边界是值和"当前行的值-expr"相等的行,如果当前行的值是null,那边界就是和当前行相等的行。
  5. expr following:当单位是rows时, 边界时当前行的后expr行。当单位是range时,边界时和"当前行的值+expr"相等的行,如果当前行的值是null,那边界就是和当前行相等的行。

在这里插入图片描述
举例:

# 取本行和前面两行
rows between 2 preceding and current row

# 取本行和之前所有的行
rows between unbounded preceding and current row

# 取本行和之后所有的行
rows between current row and unbounded following 

# 从前面三行和下面一行,总共五行
rows between 3 preceding and 1 following 

# 当 order by 后面没有 rows between 时,窗口规范默认是取本行和之前所有的行

# 当 order by 和 rows between 都没有时,窗口规范默认是分组下所有行 (rows between unbounded preceding and unbounded following)

# 当前行和当前行值减1范围 等价于 range between 1 preceding and current row。代表值的范围落在区间 [当前行值-1,当前行值] 内所有行。
# 这里的1 preceding不再是前1行的意思,而是"当前行的值-1"。
range 1 preceding 

单位rows和range的区别

建表语句

create table wf_example(
id smallint unsigned not null auto_increment primary key,
wind varchar(32),
val smallint);
 
insert into wf_example values
(null,'Window_A',1),
(null,'Window_A',2),
(null,'Window_A',2),
(null,'Window_A',3),
(null,'Window_A',3),
(null,'Window_A',3),
(null,'Window_B',100),
(null,'Window_B',200),
(null,'Window_B',300),
(null,'Window_B',400),
(null,'Window_B',500);

示例为滚动求和,计算当前行和前一行的和:

select wind,val,
sum(val) over (partition by wind order by val rows 1 preceding) 当前行和前1行的和,
sum(val) over (partition by wind order by val rows between 1 preceding and current row) 第二种定义方式
from wf_example;

在这里插入图片描述
上面示例中:

  • 第一个定义是rows 1 preceding,单位是rows(行),
  • 第一个范围是1 preceding(当单位为rows时,1 preceding 代表当前行的前1行).
  • 第一个采用了仅定义起始点的方式,终止点默认就是当前行。
  • 第二个采用了between 1 preceding and current row的方式,显式指定了起始和结束范围,效果是相同的。

我们将一个滚动求和SQL中的单位定义由rows改为range,再看一下效果:

select wind,val,
sum(val) over (partition by wind order by val range 1 preceding) range单位下当前行和当前行值减1范围的和
from wf_example;

在这里插入图片描述
面示例中,当单位变为range时:

  • 定义为 range 1 preceding,等价于 range between 1 preceding and current row。
  • 当单位为range时,这里的1 preceding不再是前1行的意思,而是"当前行的值-1"。
  • 而range between 1 preceding and current row 代表值的范围落在区间 [当前行值-1,当前行值] 内所有行。
  • 在Window_A中,第二行val值为2,因此包含值在 [2-1, 2] 范围内的所有行,即1,2,3行,sum求和结果为5,第三行同理。
  • 在Window_A中,第四行val值为3,因此包含值在 [3-1, 3] 范围内的所有行,即2,3,4,5,6行,sum求和结果为13,第五、六行同理。
  • 在Window_B中,第2行val值为200,因此包含值在[200-1, 200]范围内的所有所有行,只有第二行,sum求和结果就是自己,后面的行同理。

上面的SQL通过加入first_value和last_value函数我们可以更直观的看出边界(first_value返回内第1个值,last_value返回内最后一个值):

select wind,val,
sum(val) over (partition by wind order by val range 1 preceding) range单位下当前行和当前行值减1范围的和,
first_value(val) over (partition by wind order by val range 1 preceding) first_val,
last_value(val) over (partition by wind order by val range 1 preceding) last_val
from wf_example;

在这里插入图片描述

  • 在Window_A中,val的值差距为1,因此 range 1 preceding可以触及前面的行。
  • 在Window_B中,val的值差距为100,因此range 1 preceding无法触及前面的行(first_value和last_value都是自己),每一行的都只包含当前行自己。

但如果我们把range 1 preceding改成 range 100 preceding,则Window_B中可以触及前面的行:

select wind,val,
sum(val) over (partition by wind order by val range 100 preceding) range单位下当前行和当前行值减1范围的和,
first_value(val) over (partition by wind order by val range 100 preceding) first_val,
last_value(val) over (partition by wind order by val range 100 preceding) last_val
from wf_example;

在这里插入图片描述
可以看到Window_B中求和列变成了当前行和前1行的val的和,同时first_val变成了前1行的值(代表当前行的包含前1行)。

单位rows和range的区别总结就是:
rows是通过来划分边界,边界是明确的某一行。
range是通过来划定边界,边界是具有某个值的所有行。

缺少order by子句

根据窗口定义是否有order by子句:

  • 有 order by 子句时,默认的定义是:range between unbound preceding and current row
  • 没有 order by 子句时,默认的定义是:range between unbound preceding and unbound following

即:当有order by 子句时,是从组内第一行到当前行(注意单位是range,也包含当前行相同值的行)。当没有order by 子句时,就是从组内第1行到最后一行(组内所有行),所有的行都是相等的。

我们通过最初的sum函数来观察这种的区别:

select wind,val,
sum(val) over (partition by wind order by val) 带orderby子句,
sum(val) over (partition by wind) 不带orderby子句
from wf_example

在这里插入图片描述
上面示例中:

  • 带order by子句时,sum函数求和范围是第1行到当前行(包含和当前行相等的行)的和,sum的结果是递增的。
  • 不带order by 子句时,每一行sum,求出来都是组内全部行的和,没有order by子句,众生平等。

3、窗口函数和普通聚合函数的区别

①聚合函数是将多条记录聚合为一条; 窗口函数是每条记录都会执行,有几条记录执行完还是几条。

②聚合函数也可以用于窗口函数。

4、命名窗口

当一个窗口被多次引用的时候,在每个over后面都写一遍定义就显得有些繁琐了,此场景可以通过命名窗口优化:一次定义,多次引用。

命名窗口的定义是通过 window wind_name as () 来进行定义的,括号内的部分就是原over子句后的窗口定义,在用over关键字调用窗口时,直接引用窗口名wind_name即可:

select wind,
sum(val) over w group_sum   -- 通过名称 w 引用窗口
from wf_example
window w as (partition by wind);  -- 命名窗口定义

通常情况下使用时只需要直接引用窗口名称即可,有时需要对窗口进一步加工,例如排序等,可以用括号将窗口名扩起来,后面跟上order by 子句:

select wind,
first_value(val) over (w order by val desc) first_val_desc, -- 通过窗口名引用,并降序排列
first_value(val) over (w order by val asc) first_val_asc  -- 通过窗口名引用,并升序排列
from wf_example
window w as (partition by wind);  -- 命名窗口定义

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

k8s的对外服务--ingress

service作用体现在两个方面 1、集群内部 不断跟踪pod的变化&#xff0c;更新endpoint中的pod对象&#xff0c;基于pod的IP地址不断变化的一种服务发现机制 2、集群外部 类似负载均衡器&#xff0c;把流量ip端口&#xff0c;不涉及转发url&#xff08;http&#xff0c;https&a…

如何给新华网投稿发稿?新华网的媒体发稿方法步骤

现如今&#xff0c;互联网已经成为了人们获取信息的主要途径&#xff0c;各大媒体网站也成为了发布自己作品的首选平台。其中&#xff0c;新华网作为中国最具影响力的新闻媒体之一&#xff0c;其内容覆盖面广、触及人群众多&#xff0c;因此&#xff0c;能够在新华网上发表文章…

Django项目中的默认文件都有什么用

manager.py&#xff1a; 是django用于管理本项目的命令行工具&#xff0c;之后进行站点运行&#xff0c;数据库自动生成等都是通过本文件完成。 djangoStudy/__init__.py&#xff1a; 告诉python该目录是一个python包&#xff0c;暂无内容&#xff0c;后期一些工具的初始化可…

【华为 ICT HCIA eNSP 习题汇总】——题目集2

1、交换机某个端口配置信息如下&#xff0c;则此端口的PVID为&#xff08;&#xff09;。 A、100 B、2 C、4 D、1 # interface GigabitEthernet0/0/1 port hybrid tagged vlan 2 to 3 100 port hybrid unatgged vlan 4 6 #考点&#xff1a;VLAN&#xff08;虚拟局域网&#xff…

Hex Editor的使用教程(VS Code)

Hex Editor&#xff08;十六进制编辑器&#xff09;是一种用于查看和编辑计算机文件的低级别编辑工具。与常规文本编辑器不同&#xff0c;它允许用户直接查看和修改文件的二进制数据。在 Hex Editor 中&#xff0c;数据通常以十六进制&#xff08;hex&#xff09;格式显示&…

《C++入门篇》——弥补C不足

文章目录 前言一.命名空间二.缺省参数三.函数重载四.引用4.1引用做参数4.2引用做返回值 五.内联函数六.小语法6.1auto6.2范围for6.3空指针 前言 C是业内一门久负盛名的计算机语言&#xff0c;从C语言发展起来的它&#xff0c;不仅支持C语言的语法&#xff0c;还新添加了面向对…

分享用is_sorted()解决单调数列问题

题目名称 896. 单调数列 目录 题目名称 896. 单调数列 1.题目 2.题目分析 3.题目知识 3.1 is_sorted() 3.2.迭代器与反向迭代器 3.2.1理解迭代器 3.2.2正向迭代器 3.2.3反向迭代器 最后&#x1f368; 推荐阅读顺序: 1.题目->2.题目分析->3.题目知识点 1.题目 如…

基于R语言的NDVI的Sen-MK趋势检验

本实验拟分析艾比湖地区2010年至2020年间的NDVI数据&#xff0c;数据从MODIS遥感影像中提取的NDVI值&#xff0c;在GEE遥感云平台上将影像数据下载下来。代码如下&#xff1a; import ee import geemap geemap.set_proxy(port7890)# 设置全局网络代理 Map geemap.Map()# 指定…

安卓屏幕自动息屏时亮度突然变亮

自然息屏流程 USER_ACTIVITY_SCREEN_BRIGHT&#xff08;亮屏&#xff09; → USER_ACTIVITY_SCREEN_DIM&#xff08;DIM&#xff09; → USER_ACTIVITY_SCREEN_DREAM&#xff08;灭屏&#xff09;变化&#xff0c;最终进入ASLEEP后。在息屏时会执行一个变暗的动画 frameworks\…

echarts tooltip显示不全问题

在项目里面的tooltip数据特别多&#xff0c;显示不全问题&#xff1a; 1、如果盒子还够大&#xff0c;只是tooltip飘到上面或者下面被覆盖住了&#xff0c;可以考虑confine: true这个属性&#xff0c;将tooltip限制在盒子内; 2、如果盒子比较小&#xff0c;展示不全的话&#…

【PyTorch】PyTorch之Tensors索引切片篇

文章目录 前言一、ARGWHERE二、CAT、CONCAT、CONCATENATE三、CHUNK四、GATHER五、MOVEDIM和MOVEAXIS六、PERMUTE七、RESHAPE八、SELECT九、SPLIT十、SQUEEZE十一、T十二、TAKE十三、TILE十四、TRANSPOSE十五、UNBIND十六、UNSQUEEZE十七、WHERE 前言 介绍常用的PyTorch之Tenso…

如何使用Synology Drive作为文件同步服务器实现云同步Obsidian笔记

文章目录 一、简介软件特色演示&#xff1a; 二、使用免费群晖虚拟机搭建群晖Synology Drive服务&#xff0c;实现局域网同步1 安装并设置Synology Drive套件2 局域网内同步文件测试 三、内网穿透群晖Synology Drive&#xff0c;实现异地多端同步Windows 安装 Cpolar步骤&#…

Oracle 实战手册 工作实战经验总结

目录 一、基本的数据库管理 1、数据库的启动和关闭 ​编辑2、如何确定Oracle的版本&#xff1f; 3、如何修改数据库的内存参数 4、修改用户名密码 5、如何查看最大会话数 6、如何修改oracle数据库的用户连接数 7、解锁用户 8、如何获取被锁定的数据库对象 9、如何确定…

金融CRM系统是什么?有哪些功能和作用

今年市场经济下行&#xff0c;投资趋向于保守、人们消费降级&#xff0c;对于金融行业来说影响很大。受经济形式的影响加上行业的数字化转型升级&#xff0c;金融企业都在寻求客户管理的新策略&#xff0c;维护好忠实客户、吸引新客户投资。小编认为CRM系统是管理客户的不二之选…

计算机网络——运输层(1)暨小程送书

计算机网络——运输层&#xff08;1&#xff09;暨小程送书 小程一言专栏链接: [link](http://t.csdnimg.cn/ZUTXU) 运输层概述两个主要协议运输层和网络层的关系网络层运输层总结 多路复用与多路分解多路复用多路分解不同的技术实现时分复用&#xff08;TDM&#xff09;频分复…

maven环境搭建(打包项目)

Maven:直观来讲就是打包写好的代码封装 Apahche 软件基金会&#xff08;非营业的组织&#xff0c;把一些开源软件维护管理起来&#xff09; maven apahce的一个开宇拿项目&#xff0c;是一个优秀的项目构建&#xff08;管理工具&#xff09; maven 管理项目的jar 以及jar与j…

Netty通信中的粘包半包问题(四)

前面我们介绍了特殊分隔符、以及固定长度&#xff0c;今天来介绍一下换行符分割&#xff0c;这种换行符是兼容了Windows和Linux的转义的&#xff0c;前提你的报文中没有换行符或者对换行符做特殊处理 System.getProperty("line.separator")1.Server package splici…

使用 Categraf 采集 Nginx 指标

1. 前言 工作中需要监控 Nginx 的指标&#xff0c;选用的指标采集器是 Categraf&#xff0c;特此记录下&#xff0c;以备后用。 此文档并未详细记录详细的操作细节&#xff0c;只记录了大概的操作步骤&#xff0c;仅供参考。 2. 采集基础指标 2.1. 暴露 Nginx 自带的指标采…

「2023 | 快手」PEPNet:融合个性化先验信息的多场景多任务网络

之前梳理过多场景建模方法&#xff1a;推荐系统(二十四&#xff09;「知识梳理」多场景建模梳理&#xff0c;现在介绍快手提出的多场景多任务方法PEPNet。 Title: PEPNet: Parameter and Embedding Personalized Network for Infusing with Personalized Prior Information F…

GMT学习记录

我主要根据GMT中文手册一步一步学习的&#xff01;&#xff01;&#xff01;&#xff01;B站视频介绍的是5.0老版本仅仅建立基础理解这个软件。 好的&#xff0c;学了一点发现直接把gmt转为shp&#xff0c;就得到我想的文件 gmt数据转shape格式数据 - 简书 (jianshu.com) 命…