首页 > 数据库 >SQL窗口函数OVER详细用法

SQL窗口函数OVER详细用法

时间:2023-07-13 11:46:12浏览次数:63  
标签:函数 OVER RANK 用法 SQL 排序 ORDER SELECT

# SQL窗口函数OVER详细用法

OVER的定义:

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

OVER的语法

OVER ( [ PARTITION BY column ] [ ORDER BY culumn ] )

PARTITION BY 子句进行分组; ORDER BY 子句进行排序。

窗口函数OVER()指定一组行,开窗函数计算从窗口函数输出的结果集中各行的值。

开窗函数不需要使用GROUP BY就可以对数据进行分组,还可以同时返回基础行的列和聚合列。

OVER的用法:

OVER开窗函数必须与聚合函数或排序函数一起使用,聚合函数一般指SUM(),MAX(),MIN,COUNT(),AVG()等常见函数。排序函数一般指RANK(),ROW_NUMBER(),DENSE_RANK(),NTILE()等。

OVER在聚合函数中使用的示例 :我们以SUM和COUNT函数作为示例来给大家演示。

建立测试表和测试数据

CREATE TABLE Employee  ( 
ID INT PRIMARY KEY, 
Name VARCHAR(20), 
GroupName VARCHAR(20),
Salary INT
) 

INSERT INTO Employee 
VALUES(1,'小明','开发部',8000),    (4,'小张','开发部',7600),    (5,'小白','开发部',7000), 
   (8,'小王','财务部',5000),    (9, null,'财务部',NULL),    (15,'小刘','财务部',6000), 
   (16,'小高','行政部',4500),    (18,'小王','行政部',4000),   (23,'小李','行政部',4500), 
   (29,'小吴','行政部',4700);

SUM后的开窗函数

SELECT *,
   SUM(Salary) OVER(PARTITION BY Groupname) 每个组的总工资,
   SUM(Salary) OVER(PARTITION BY groupname ORDER BY ID) 每个组的累计总工资,
   SUM(Salary) OVER(ORDER BY ID) 累计工资,
   SUM(Salary) OVER() 总工资
from Employee

结果如下:
image-20230713112336326

其中开窗函数的每个含义不同,我们来具体解读一下:
SUM(Salary) OVER (PARTITION BY Groupname)
只对PARTITION BY后面的列Groupname进行分组,分组后求解Salary的和。
SUM(Salary) OVER (PARTITION BY Groupname ORDER BY ID)
对PARTITION BY后面的列Groupname进行分组,然后按ORDER BY 后的ID进行排序,然后在组内对Salary进行累加处理。

SUM(Salary) OVER (ORDER BY ID)
只对ORDER BY 后的ID内容进行排序,对排完序后的Salary进行累加处理。
SUM(Salary) OVER ()
对Salary进行汇总处理

COUNT后的开窗函数

SELECT *,
​    COUNT(*) OVER(PARTITION BY Groupname ) 每个组的个数, 
​    COUNT(*) OVER(PARTITION BY Groupname ORDER BY ID) 每个组的累积个数, 
​    COUNT(*) OVER(ORDER BY ID) 累积个数 ,
​    COUNT(*) OVER() 总个数
from Employee

返回的结果如下图:
image-20230713112501993

后面的每个开窗函数就不再一一解读了,可以对照上面SUM后的开窗函数进行一一对照。

OVER

在排序函数中使用的示例

我们对4个排序函数一一演示

先建立测试表和测试数据

WITH t AS
(SELECT 1 StuID,'一班' ClassName,70 Score
UNION ALL
SELECT 2,'一班',85
UNION ALL
SELECT 3,'一班',85
UNION ALL
SELECT 4,'二班',80
UNION ALL
SELECT 5,'二班',74
UNION ALL
SELECT 6,'二班',80
)

SELECT * INTO Scores FROM t;
SELECT * FROM Scores

ROW_NUMBER()

定义:ROW_NUMBER()函数作用就是将SELECT查询到的数据进行排序,每一条数据加一个序号,他不能用做于学生成绩的排名,一般多用于分页查询,比如查询前10个 查询10-100个学生。ROW_NUMBER()必须与ORDER BY一起使用,否则会报错。
对学生成绩排序

SELECT *,
ROW_NUMBER() OVER (PARTITION BY ClassName ORDER BY SCORE DESC) 班内排序,
ROW_NUMBER() OVER (ORDER BY SCORE DESC) AS 总排序
FROM Scores;

image-20230713112551243

这里的PARTITION BY和ORDER BY的作用与我们在上面看到的聚合函数的作用一样,都是用来进行分组和排序使用的。
此外ROW_NUMBER()函数还可以取指定顺序的数据。

SELECT *, ROW_NUMBER() OVER (ORDER BY SCORE DESC) AS 总排序
FROM Scores
) t WHERE t.总排序=2;```

结果如下:
image-20230713112709778

RANK()

定义:RANK()函数,顾名思义排名函数,可以对某一个字段进行排名,这里和ROW_NUMBER()有什么不一样呢?ROW_NUMBER()是排序,当存在相同成绩的学生时,ROW_NUMBER()会依次进行排序,他们序号不相同,而Rank()则不一样。如果出现相同的,他们的排名是一样的。下面看例子:

示例
image-20230713112726544
其中上图是ROW_NUMBER()的结果,下图是RANK()的结果。当出现两个学生成绩相同是里面出现变化。RANK()是1-1-3-3-5-6,而ROW_NUMBER()则还是1-2-3-4-5-6,这就是RANK()和ROW_NUMBER()的区别了。

DENSE_RANK()

定义:DENSE_RANK()函数也是排名函数,和RANK()功能相似,也是对字段进行排名,那它和RANK()到底有什么不同那?特别是对于有成绩相同的情况,DENSE_RANK()排名是连续的,RANK()是跳跃的排名,一般情况下用的排名函数就是RANK() 我们看例子:

SELECT 
RANK() OVER (ORDER BY SCORE DESC) AS [RANK],* 
FROM Scores; 
SELECT 
DENSE_RANK() OVER (ORDER BY SCORE DESC) AS [RANK],* 
FROM Scores;

结果如下:
image-20230713112740496

上面是RANK()的结果,下面是DENSE_RANK()的结果

NTILE()

定义:NTILE()函数是将有序分区中的行分发到指定数目的组中,各个组有编号,编号从1开始,就像我们说的'分区'一样 ,分为几个区,一个区会有多少个。

SELECT *,NTILE(1) OVER (ORDER BY SCORE DESC) AS 分区后排序 FROM Scores; 
SELECT *,NTILE(2) OVER (ORDER BY SCORE DESC) AS 分区后排序 FROM Scores; 

image-20230713112812438

image-20230713112825697

image-20230713112835328

就是将查询出来的记录根据NTILE函数里的参数进行平分分区。

总结 :

OVER开窗函数是我们工作中经常要使用到的,特别是在做数据分析计算的时候,经常要对数据进行分组排序。上面我们额外介绍了聚合函数和排序函数的与OVER结合的使用方法,此外还有很多与OVER一起使用的函数,比如LEAD函数,LAG函数,STRING_AGG函数等等都会使用到开窗函数OVER,其使用方法也要务必掌握。

标签:函数,OVER,RANK,用法,SQL,排序,ORDER,SELECT
From: https://www.cnblogs.com/HeroZhang/p/17549959.html

相关文章

  • PHP 生成数据库的 markdown 字段说明文档,支持 mysql,postgresql
    安装composerrequirepeng49/db2markdown命令行使用phpvendor/bin/db2markdown输入数据库的地址(host),端口(port)用户名,密码,要导出的表,默认是*,生成所有表的文档,指定多个表明用逗号隔开,如:table1,table2$phpsrc/bin/db2markdownpleaseenterthedb(1mys......
  • 如何实现省市县 mysql的具体操作步骤
    省市县MySQL数据库设计与应用在开发一个基于地理位置的应用系统时,常常需要使用到省市县的数据。为了方便地对这些数据进行管理和查询,我们可以使用MySQL数据库来存储和操作省市县数据。本文将介绍如何设计和应用一个基于MySQL的省市县数据库,并提供相应的代码示例。数据库设......
  • SQL Server SQL执行顺序
    SQLServerSQL执行顺序下面是对应用于SQLserver2000和SQLServer2005的各个逻辑步骤的简单描述。(8)SELECT (9)DISTINCT  (11)<Top Num> <select list>(1)FROM [left_table](3)<join_type> JOIN <right_table>(2)        ON <join_condition>(4)W......
  • vim:用法
    学习自:Linuxvi/vimvim使用教程图文教程(零基础超详细)1、何为vimvim是从vi发展而来的一种文本编辑器,是一种程序开发工具。具有代码补全、编译、错误跳转等方便编程的功能。vim官网:https://www.vim.org/2、vim键盘图3、vim模式vim有3种模式:命令(Command):该模式下敲击键盘会......
  • 如何实现只有80对外开放的宿主机,使用docker实现mysql和redis和外部通信的具体操作步
    使用Docker实现MySQL和Redis与外部通信引言在现代软件开发中,往往需要使用到各种数据库和缓存技术。MySQL是一种常用的关系型数据库,而Redis是一种常用的内存缓存数据库。在部署这些数据库和缓存时,我们常常需要与外部的系统进行通信,例如通过网络连接,提供服务给其他系统。本文将介绍......
  • 怎么在数据库里关闭mysqlbinlog 这个问题怎么解决?
    项目方案:关闭MySQLBinlog1.项目背景MySQLBinlog是MySQL数据库的事务日志,它记录了数据库的所有操作,包括插入、更新和删除等操作。在某些情况下,我们可能需要关闭MySQLBinlog来提高数据库的性能或保护敏感数据。2.方案介绍本方案将介绍如何在MySQL数据库中关闭MySQLBinlog。......
  • 怎么提升mysql批量更新速度 这个问题怎么解决?
    项目方案:提升MySQL批量更新速度1.简介在开发过程中,我们可能会遇到需要批量更新大量数据的情况,而MySQL默认的单条更新语句执行效率较低,不能满足高效更新的需求。因此,我们需要通过一些优化方案来提升MySQL批量更新的速度。2.方案2.1.使用事务在进行批量更新时,将多个更......
  • 如何实现在linux连接Windows的mysql的命令的具体操作步骤
    在Linux连接Windows的MySQL的命令作为一名经验丰富的开发者,我将会教给你如何在Linux环境下连接到Windows的MySQL数据库。下面是整个过程的步骤,以及每一步所需要执行的操作和相应的代码。连接步骤步骤操作1安装MySQL客户端2配置远程访问权限3连接到Windows的My......
  • python-pymysql-类对象映射为sql语句
    查询语句importpymysqlclassUserQuery:def__init__(self,name=None,age=None,email=None):self.name=nameself.age=ageself.email=emaildefselect_data(table,condition):#连接到数据库connection=pymysql.connec......
  • Mac 苹果电脑软件 crossOver 可以直接运行 windows 应用软件,强强
    首先我们可以先了解一下什么是crossOver,CrossOver是Mac和Windows系统之间的兼容工具。使Mac操作系统的用户可以运行Windows系统的应用,从办公软件、实用工具、游戏到设计软件,您都可以在Mac程序和Windows程序之间随意切换。那我们该如何使用CrossOver来安装使用......