MySQL:开窗函数

news2025/2/27 2:51:09

当查询条件需要用到复杂子查询时,聚合函数操作起来非常麻烦,因此使用开窗函数能够轻松实现。

注意:在Oracle中称为分析函数。

           在MySQL中称为开窗函数,使用于MySQL8.0以上版本,sql sever、hive、Oracle等。

1 开窗函数

开窗函数:为将要被操作的行的集合定义一个窗口,它对一组值进行操作,不需要使用GROUP BY子句对数据进行分组,能够在同一行中同时返回基础行的列和聚合列。

语法:函数 + over(partition by <分组用列> order by <排序用列>)

over() 按所有行进行分组

over(partition by xxx)按xxx分组的所有行进行分组

over(partition by xxx order by aaa)按列xxx分组,按列aaa排序

over(order by aaa) 按aaa列排序

括号中的两个关键词partition by 和order by可以只出现一个。

开窗函数表示对数据集按照分组用列进行分区,并且对每个分区按照函数聚合计算,最终将计算结果按照排序用列排序后返回到该行。

无论何种能力,窗口函数都不会影响数据行数,而是将计算平摊在每一行。

1.1 开窗函数分类

名称描述
cume_dist()计算一组值中一个值的累积分布
dense_rank()根据该order by子句为分区中的每一行分配一个等级。它将相同的等级分配给具有相等值的行。如果两行或更多行具有相同的排名,则排名值序列中将没有间隙
first_value()返回相对于窗口框架第一行的指定表达式的值
lag()返回分区中当前行之前的第N行的值。如果不存在前一行,则返回NULL
last_value()返回相对于窗口框架中最后一行的指定表达式的值
lead()返回分区中当前行之后的第N行的值。如果不存在后续行,则返回NULL
nth_value()从窗口框架的第N行返回参数的值
ntile()将每个窗口分区的行分配到指定数量的排名组中
percent_rank()计算分区域结果集中行的百分数等级
rank()与dense_rank()函数相似,不同之处在于当两行或更多行具有相同的等级时,等级值序列中存在间隙
row_number()为分区中的每一行分配一个顺序整数

按照函数功能不同,MySQL支出的开窗函数分为如下几类:

  • 序号函数:row_number() / rank() / dense_rank()
  • 分布函数:percent_rank() / cume_dist()
  • 前后函数:lag() / lead()
  • 头尾函数:first_value() / last_value()
  • 其他函数 :nth_value() / nfile()

2 排序开窗函数和聚合开窗函数

2.1 排序开窗函数

  • row_number(行号)
  • rank(排名)
  • dense_rank(密集排名)
  • ntile(分组排名)

例1 先对所有数据进行排序

select s.sid,s1.sname,s1.gender,c.cname,s.num,   row_number() over 
(partition by c.cname order by num desc) as row_number排名,   
rank() over (partition by c.cname order by num desc) as rank排名,   
dense_rank() over (partition by c.cname order by num desc) as dense_rank排名,   
ntile(6) over (partition by c.cname order by num desc) as ntile排名    
from score s   join student s1 on s.student_id = s1.sid   
left join course c on s.course_id = c.cid

结果如下:

 row_number

根据课程进行分组,然后对每组内的成绩进行降序排序

又上图可知row_number对于同组内的相同成绩并没有做特殊处理,而仅仅是生成连续的序号。row_number常用于按照某列生成连续序号。

rank

rank函数就是对查询出来的记录进行排名。

与row_number函数不同的是,rank函数考虑到了over子句中排序字段值相同的情况,over子句中排序字段值相同的序号是一样的,后面字段值不相同的序号将跳过相同的排名号排下一个,也就是相关行之前的排名数加一,通过上面的例子我们也可以看出,rank考虑到值相同情况,并且它的排名存在跳跃性。

dense_rank

密集排名,在考虑了值相同时,排名也相同,但是序号不跳跃,紧跟上一个序号。

例如题目中体育成绩有2位同学(张三和刘三)并列第一,如果使用rank排名 ,那钢蛋就是第三名,而如果采用dense_rank 那钢蛋就是第二名,这个很容易理解吧。

ntile

ntile会先根据你的分组依据,本题中是课程名称,然后把每个组的总记录数进行按照你给的ntile()里的数字进行,这个数字就是桶数,相当于是把体育课程总共12条记录,尽量等划分成5桶,然后按照num的排序等级划分,每个桶两条记录,也就是112233445566的排序结果了,很显然,这个排序结果的数字大小只能用于桶与桶之间,而桶内部记录虽然序号相同,但是num不一定相同。

例如:统计各科成绩前三 

select * from 
(select s.sid,s1.sname,s1.gender,c.cname,s.num,dense_rank() 
over (partition by c.cname order by num desc) as dense_rank排名 from score s
join student s1 on s.student_id = s1.sid
left join course c on s.course_id = c.cid) as e
where dense_rank排名 <= 3;

2.2 聚合开窗函数

函数名如果是聚合函数,则称为聚合开窗函数

语法:聚合函数(列) over(partition by 列 order by 列)

常见的聚合函数有:sum()、count()、average()、max()、min()

计算每个学生的及格科目数

select student_id,count(sid) from  score where num>= 60 group by student_id;

通过普通的聚合函数分组计算后,数据表结构发生了变化,它会根据分组进行显示,并且,如果你是根据学生ID分组,那你查询的字段应该也是学生ID,不然会影响到分组结果所对应的数值,例如现在查询条件在添加一个Sid

select sid,student_id,count(sid) from  score where num>= 60 group by student_id;

 

sid的数据并没有实际意义,因为数据表已经根据分组发生了变化。

执行结果

select sid,student_id,count(sid) over(PARTITION by student_id order
 by student_id) 及格数   from score where num>= 60;

 

 总结:开窗函数不会修改源数据表的结果,也是在表的最后一列添加想要的结果。

实例数据

CREATE TABLE class (
  cid int(11) NOT NULL AUTO_INCREMENT,
  caption varchar(32) NOT NULL,
  PRIMARY KEY (cid)
) ENGINE=InnoDB CHARSET=utf8;

INSERT INTO class VALUES
(1, '三年二班'), 
(2, '三年三班'), 
(3, '一年二班'), 
(4, '二年九班');

CREATE TABLE teacher(
  tid int(11) NOT NULL AUTO_INCREMENT,
  tname varchar(32) NOT NULL,
  PRIMARY KEY (tid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO teacher VALUES
(1, '张磊老师'), 
(2, '李平老师'), 
(3, '刘海燕老师'), 
(4, '朱云海老师'), 
(5, '李杰老师');

CREATE TABLE course(
  cid int(11) NOT NULL AUTO_INCREMENT,
  cname varchar(32) NOT NULL,
  teacher_id int(11) NOT NULL,
  PRIMARY KEY (cid),
  KEY fk_course_teacher (teacher_id),
  CONSTRAINT fk_course_teacher FOREIGN KEY (teacher_id) REFERENCES teacher (tid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO course VALUES
(1, '生物', 1), 
(2, '物理', 2), 
(3, '体育', 3), 
(4, '美术', 2);

CREATE TABLE student(
  sid int(11) NOT NULL AUTO_INCREMENT,
  gender char(1) NOT NULL,
  class_id int(11) NOT NULL,
  sname varchar(32) NOT NULL,
  PRIMARY KEY (sid),
  KEY fk_class (class_id),
  CONSTRAINT fk_class FOREIGN KEY (class_id) REFERENCES class (cid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO student VALUES
(1, '男', 1, '理解'), 
(2, '女', 1, '钢蛋'), 
(3, '男', 1, '张三'), 
(4, '男', 1, '张一'), 
(5, '女', 1, '张二'), 
(6, '男', 1, '张四'), 
(7, '女', 2, '铁锤'), 
(8, '男', 2, '李三'), 
(9, '男', 2, '李一'), 
(10, '女', 2, '李二'), 
(11, '男', 2, '李四'), 
(12, '女', 3, '如花'), 
(13, '男', 3, '刘三'), 
(14, '男', 3, '刘一'), 
(15, '女', 3, '刘二'), 
(16, '男', 3, '刘四');

CREATE TABLE score (
  sid int(11) NOT NULL AUTO_INCREMENT,
  student_id int(11) NOT NULL,
  course_id int(11) NOT NULL,
  num int(11) NOT NULL,
  PRIMARY KEY (sid),
  KEY fk_score_student (student_id),
  KEY fk_score_course (course_id),
  CONSTRAINT fk_score_course FOREIGN KEY (course_id) REFERENCES course (cid),
  CONSTRAINT fk_score_student FOREIGN KEY (student_id) REFERENCES student(sid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO score VALUES
(1, 1, 1, 10),
(2, 1, 2, 9),
(5, 1, 4, 66),
(6, 2, 1, 8),
(8, 2, 3, 68),
(9, 2, 4, 99),
(10, 3, 1, 77),
(11, 3, 2, 66),
(12, 3, 3, 87),
(13, 3, 4, 99),
(14, 4, 1, 79),
(15, 4, 2, 11),
(16, 4, 3, 67),
(17, 4, 4, 100),
(18, 5, 1, 79),
(19, 5, 2, 11),
(20, 5, 3, 67),
(21, 5, 4, 100),
(22, 6, 1, 9),
(23, 6, 2, 100),
(24, 6, 3, 67),
(25, 6, 4, 100),
(26, 7, 1, 9),
(27, 7, 2, 100),
(28, 7, 3, 67),
(29, 7, 4, 88),
(30, 8, 1, 9),
(31, 8, 2, 100),
(32, 8, 3, 67),
(33, 8, 4, 88),
(34, 9, 1, 91),
(35, 9, 2, 88),
(36, 9, 3, 67),
(37, 9, 4, 22),
(38, 10, 1, 90),
(39, 10, 2, 77),
(40, 10, 3, 43),
(41, 10, 4, 87),
(42, 11, 1, 90),
(43, 11, 2, 77),
(44, 11, 3, 43),
(45, 11, 4, 87),
(46, 12, 1, 90),
(47, 12, 2, 77),
(48, 12, 3, 43),
(49, 12, 4, 87),
(52, 13, 3, 87);

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

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

相关文章

Redis为什么能抗住10万并发?揭秘性能优越的背后原因

1. Redis简介 Redis是一个开源的&#xff0c;基于内存的&#xff0c;高性能的键值型数据库。它支持多种数据结构&#xff0c;包含五种基本类型 String&#xff08;字符串&#xff09;、Hash&#xff08;哈希&#xff09;、List&#xff08;列表&#xff09;、Set&#xff08;集…

Win10的两个实用技巧系列之华硕电脑设置面部识别的技巧、删除背景图片的方法

Win10系统的华硕电脑怎么使用人脸解锁? 华硕电脑设置面部识别的技巧 Win10系统的华硕电脑怎么使用人脸解锁&#xff1f;华硕电脑想要添加面部识别&#xff0c;方便人脸解锁&#xff0c;下面我们就来看看华硕电脑设置面部识别的技巧 有些使用Win10系统的华硕电脑的用户&#…

X509证书以及相关java常用接口

二、X509证书 X.509证书是一种数字证书标准&#xff0c;用于验证在计算机网络中的身份认证。它们是由权威机构&#xff08;例如CA&#xff09;发行&#xff0c;包含有关证书持有者身份信息的数字签名。X.509证书通常用于SSL / TLS协议&#xff0c;以确保客户端和服务器之间的安…

Word转PDF:一键转换,快速高效

在现代的工作和学习中&#xff0c;我们经常需要将Word文档转换成PDF文件以便于分享和保留格式。虽然Word软件自身也可以保存为PDF格式&#xff0c;但在某些情况下&#xff0c;我们需要一个更快捷、高效的转换工具来帮助我们完成任务。下面将介绍一款快速高效的Word转PDF在线转换…

机器学习与深度学习——通过SVM线性支持向量机分类鸢尾花数据集iris求出错误率并可视化

线性支持向量机 先来看一下什么叫数据近似线性可分&#xff0c;如下图所示&#xff0c;蓝色圆点和红色圆点分别代表正类和负类&#xff0c;显然我们不能找到一个线性的分离超平面将这两类完全正确的分开&#xff1b;但是如果将数据中的某些特异点(黑色箭头指向的点)去除之后&a…

华为ensp配置实验大全(免费持续更新)

点开一篇文章 &#xff0c;“分享”要收费。 点开一篇文章&#xff0c; "大全"但就两个实验。 点开一篇文章&#xff0c; “详细"但全截图。 我忽略了最重要的东西"产品说明书" 产品说明书优势 "规范" "详细" 此文寻找官方手册中…

BUUCTF-PWN-[第五空间2019 决赛]PWN5

这题考到 格式化字符串的方法 我之前没有学过 根据wp写完这题去看看原理 下载打开环境 checksec看看 发现有三个保护 nx打开 所以无法写入shellcode 现在看看ida32 发现/bin/sh 进去看 发现就在主函数里面 我们进行代码审计 发现输入名字 他会返回名字 然后再输入密码 如果…

MJ优质博主清单;把ChatGPT调教为英语私教;绝美SD Prompt手册;AgentGPT体验全记录;2项AI工具最强更新 | ShowMeAI日报

&#x1f440;日报&周刊合集 | &#x1f3a1;生产力工具与行业应用大全 | &#x1f9e1; 点赞关注评论拜托啦&#xff01; &#x1f916; 『预测五年后的应聘场景』玩转机器人将是核心竞争优势 1. 你有多少个公用机器人&#xff08;基本的机器人操作能力&#xff09; 2. 你…

体验亚马逊云科技产品使用 AWS Amplify 构建和部署一个 Web 应用程序

前言如果你是IT从业者&#xff0c;会有一个非常明显的感觉&#xff0c;那就是上云已经成为了趋势。以前公司如果有什么互联网业务&#xff0c;都要自己买服务器&#xff0c;自建机房&#xff0c;或者搬到运营商的IDC机房里面去进行托管。但现在&#xff0c;大家都是找云服务器厂…

Java用IO实现简单的用户注册登录并玩猜数字小游戏demo

项目场景&#xff1a; 简单的用Java IO读写操作完整实现用户注册登录并玩猜数字小游戏案例。 &#xff08;猜数字游戏&#xff1a;系统随机生成一位1-100之间的数字让用户猜&#xff0c;给出猜大了&#xff0c;猜小了&#xff0c;及第几次猜对了的提示&#xff09; 分析&#…

Shell基础知识汇总

一、变量 1.变量的类型 变量根据作用范围的大小主要分为局部变量、全局变量、环境变量&#xff1a; &#xff08;1&#xff09;局部变量&#xff1a;在Shell脚本中的函数内显示使用local关键字定义的变量。其作用域局限于函数内&#xff0c;当local变量名与global变量名同名时…

激活函数高频面试题集合

激活函数激活函数的作用是什么&#xff1f;常用的激活函数Relu引入Relu的原因Relu顺序relu在零点可导吗&#xff0c;不可导如何进行反向传播&#xff1f;Geluleaky relu优点缺点softmaxsigmoid缺陷tanh缺点如何选择激活函数Bert、GPT、GPT2中用的激活函数是什么&#xff1f;为什…

我在chatgpt学习requestIdleCallback

react对接chatgpt&#xff0c;导入json形成记忆数据继续提问&#xff0c;想要私聊 [{"role": "user","content": "requestIdleCallback 怎么使用" }, {"role": "assistant","content": "requestI…

电子采购系统的优缺点分析及选型建议

在现今&#xff0c;电子采购系统的出现&#xff0c;为企业采购带来了全新的解决方案。它可以使采购过程更加自动化、高效化&#xff0c;减少采购成本和人力资源的浪费。本文将对电子采购系统的优缺点进行分析&#xff0c;并提供选型建议。 电子采购系统优点&#xff1a; 1、自…

(Linux) make/makefile的简单介绍以及使用

make和makefile的功能make和makefile的使用规则make和makefile的功能 什么是make和makefile,它有什么作用&#xff1f;我相信这是大部分人在刚接触make和makefile时疑惑。那我们就一起来看看它的答案吧。 make是一条命令&#xff0c;makefile是一个文件&#xff0c;两个搭配使…

基于ZC序列的帧同步

Zadoff-Chu序列是一种特殊的序列&#xff0c;具有良好的自相关性和很低的互相关性&#xff0c;这种性能可以被用来产生同步信号&#xff0c;作为对时间和频率的相关运算在TD-LTE系统中&#xff0c;Zadoff-Chu(ZC)序列主要应用于上行RS序列生成、PRACH前导序列生成以及主同步信号…

CIMCAI mature AI product, digital port intelligent port waterway

全球港航人工智能领军企业中集飞瞳CIMCAI&#xff0c;成熟港航人工智能产品全球领先&#xff0c;核心技术世界顶尖水平数字化港航自动化。全球集装箱人工智能AI领军企业CIMCAI中集飞瞳&#xff0c;全球航运港口高科技领军企业&#xff0c;率先将港口人工智能Ceaspectus™产品做…

python入门(六) opencv的安装,图片操作,绘制文字图形,视频操作

文章目录课程目标认识openCV如何安装openCVOpenCV 读取、缩放、翻转、写入图像读取图片缩放图片翻转图片写入图片openCV绘制图形和文字创建一个纯黑色的底图画一个矩形再画一个正方形再画一个圆形再画一个实心圆画一条线画多边形在真实的图片上加载图形在真实的图片上加载文字O…

创建菜单栏、菜单、菜单项

1、QMainWindow窗口 1.1、创建菜单栏 this 代表的是 当前窗口&#xff08;主窗口&#xff09;&#xff0c;也就是 当前窗口中添加/设置 菜单栏 this->resize(800,600); //创建 菜单栏 QMenuBar *menuBar new QMenuBar(this); //将菜单栏 添加到主窗口的特殊位置 this-&g…

第12届蓝桥杯省赛真题剖析-2020年12月20日Scratch编程初级组

[导读]&#xff1a;超平老师的《Scratch蓝桥杯真题解析100讲》已经全部完成&#xff0c;后续会不定期解读蓝桥杯真题&#xff0c;这是Scratch蓝桥杯真题解析第123讲。 第12届蓝桥杯省赛举办了两次&#xff0c;这是2020年10月20日举行的第一次省赛初级组试题&#xff0c;比赛仍…