窗口函数-分组排序:row_number()、rank() 、dense_rank()、ntile()

窗口函数语法结构:

分析函数() over(partition by 分组列名 order by 排序列名 rows between 开始位置 and 结束位置)

开窗函数和聚合函数区别:

聚合函数会对一组值进行计算并返回一个值,常见的比如sum(),count(),max(),min(), avg(),会与group by一起使用。

注意其中只有count不忽略null值,COUNT(a):返回非空值的数量。COUNT(*):返回所有行的数量(不区分空值)。

count(0)=1

ROW_NUMBER()

有些场景比如求各个班或各个学科的前几名,这时候需要每一组返回多个值,就需要开窗函数解决。

比如现在有一部分学生成绩,来自不同的班级:

求所有人中的前几名学生:

首先想到SELECT * FROM temp ORDER BY sroce DESC 这是对分数倒序排序,如果想只要前几名名,需要生成一个序号,所以使用ROW_NUMBER()。不分组

sql 复制代码
SELECT name,class,score, ROW_NUMBER() OVER(ORDER BY score DESC) mm FROM temp

如果对于班级分组 加上PARTITION BY class

sql 复制代码
SELECT name,class,score 
FROM ( 
	SELECT name,class,score, 
		RANK() OVER(PARTITION BY class ORDER BY score) mm 
		FROM temp 
	) a 
	WHERE mm = 1;

--这里引用博客:[窗口函数over] (https://blog.csdn.net/qq_55342245/article/details/122300899)的例子

RANK() DENSE_RANK()

进一步,如果只要第一名,或者最后一名就不能用row_number(),因为如果同班有两个并列第一,mm=1就只返回一个结果。使用RANK()

查询每个班的第一名的成绩:

SELECT name,class,score 
FROM (
	SELECT name,class,score, 
	RANK() OVER(PARTITION BY class ORDER BY score DESC) mm 
	FROM TEMP 
	) a 
	WHERE mm = 1;

RANK()在处理相同值时序号一样,但是会占位,排名可能是:12225

DENSE_RANK()在处理相同值时序号一样,但是不会占位,数字连续出现:12223

NTILE()

NTILE函数是用来将数据切割成指定数量的桶(buckets),并将每个数据行分配到对应的桶中。它可用于将数据划分为相等的小切片,为每一行分配该小切片的数字序号。

NTILE不支持ROWS BETWEEN,比如NTILE(2) OVER(PARTITION BY dept_no ORDER BY salary ROWS BETWEEN 3 PRECEDING - AND CURRENT ROW)。

搬运一些例子便于理解:

sql 复制代码
SELECT name, dept_no, salary,
       ntile(2) over(order by salary) n1,
       -- 全局按照salary升序排列,数据切成2份
       ntile(2) over(partition by dept_no order by salary) n2, 
       -- 按照dept_no分组,在分组内按照salary升序排列,数据切成2份
       ntile(3) over(partition by dept_no order by salary) n3 
       -- 按照dept_no分组,在分组内按照salary升序排列,数据切成3份
FROM data;

对于第三个例子:

NTILE(3) OVER(PARTITION BY dept_no ORDER BY salary)是根据dept_no列进行分组,意味着每个部门的数据会独立进行切割成3份。数据在每个分组内根据salary排序,然后再将排序后的数据切割成3份,并且每份数据的大小相对均匀。


参考自:窗口函数之ntile()函数讲解https://blog.csdn.net/godlovedaniel/article/details/116571187

总结&区别

select ROW_NUMBER()over(order by name) as 排序,* from temp

--- 排序,即使值一样,也不会重复排序。例如1,2,3,4,5

select RANK()over(order by name) as 排序,* from temp

--- 排序,值一样,就重复排序,有间隙。例如1,1,3,4

select DENSE_RANK()over(order by name) as 排序,* from temp

--- 排序,值一样,就重复排序,没有间隙。例如1,1,2,2,3,4,5

select NTILE(2)over(order by name) as 排序,* from temp

--- 排序,分成2组。此函数一般用于取表中前百分之几的数据。例如,取数据的前25%就将数据分4组,然后字段的条件是等于1。

--这里引用博客:[窗口函数over](https://blog.csdn.net/qq_55342245/article/details/122300899)的例子

相关推荐
数据龙傲天7 分钟前
1688商品API接口:电商数据自动化的新引擎
java·大数据·sql·mysql
engineer-gxd42 分钟前
MySQL 表的操作
mysql
cyt涛1 小时前
MyBatis 学习总结
数据库·sql·学习·mysql·mybatis·jdbc·lombok
看山还是山,看水还是。2 小时前
MySQL 管理
数据库·笔记·mysql·adb
momo小菜pa2 小时前
【MySQL 09】表的内外连接
数据库·mysql
Jasonakeke3 小时前
【重学 MySQL】四十九、阿里 MySQL 命名规范及 MySQL8 DDL 的原子化
数据库·mysql
小宇成长录3 小时前
Mysql:数据库和表增删查改基本语句
数据库·mysql·数据库备份
团儿.4 小时前
解锁MySQL高可用新境界:深入探索MHA架构的无限魅力与实战部署
数据库·mysql·架构·mysql之mha架构
权^5 小时前
MySQL--聚合查询、联合查询、子查询、合并查询(上万字超详解!!!)
大数据·数据库·学习·mysql
万事大吉CC8 小时前
mysql单表查询·3
数据库·mysql