使用MySQL开窗函数之前一定先确定当前数据库版本是否支持,因为只有MySQL8.0以上的版本才支持开窗函数

用navicat如何查看MySQL的版本的方法:

在出现的界面输入命令  select version();

窗口函数(数据分析-SQL高阶(窗口函数) - 哔哩哔哩 (bilibili.com)
窗口函数也称为OLAP(Online Analytical Processing)函数,意思是对数据库数据进行实时分析处理,窗口函数在Oracle和SQL Server 中也被称为分析函数,窗口函数语法如下

<窗口函数> OVER ([PARTITION BY <列清单>]           ORDER BY <排序用列清单> [框架])

语法中<>中的内容不可省略,[]中的内容可以省略。即PARTIION BY和框架可以省略,ORDER BY 不可以省略。框架对汇总范围进行限定。

(ROWS | RANGE) BETWEEN (UNBOUNDED | [num]) PRECEDING AND ([num] PRECEDING | CURRENT ROW | (UNBOUNDED | [num]) FOLLOWING) (ROWS | RANGE) BETWEEN CURRENT ROW AND (CURRENT ROW | (UNBOUNDED | [num]) FOLLOWING) (ROWS | RANGE) BETWEEN [num] FOLLOWING AND (UNBOUNDED | [num]) FOLLOWING

窗口函数: 1)可以作为窗口函数的聚合函数。

SUM :求和

MIN :最小值

MAX :最大值

AVG :平均值

COUNT :计数

2)专用窗口函数

RANK :跳跃排序,排序:1,1,3

DENSE_RANK :连续排序,排序:1,1,2

ROW_NUMBER:没有重复值的排序,排序:1,2,3

FIRST_VALUE :返回组中数据窗口的第一个值

LAST_VALUE :返回组中数据窗口的最后一个值。

LAG :LAG(col,n,DEFAULT) 用于统计窗口内往上第n行值。

LEAD :LEAD(col,n,DEFAULT) 用于统计窗口内往下第n行值。

窗口函数实操
先创建一张产品表

create table product ( product_id int(4) COMMENT 'ID', product_name varchar(10) COMMENT '产品名称', product_type varchar(10) COMMENT '产品类型', sale_price int(4) COMMENT '价格' )ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='产品清单'

插入数据

insert into product(product_id,product_name,product_type,sale_price) values(1,'叉子','厨房用具',500),(2,'擦菜板','厨房用具',880), (3,'菜刀','厨房用具',3000),(4,'高压锅','厨房用具',6800),(5,'T恤衫','衣服',1000),(6,'运动T恤','衣服',4000),(7,'圆珠笔','办公用品',100),(8,'打孔器','办公用品',500);

结果表如图

1)可以作为窗口函数的聚合函数。

sum求和(累计值)

SELECT product_id, product_name, product_type, sale_price, SUM(sale_price) OVER (PARTITION BY product_type ORDER BY sale_price range BETWEEN UNBOUNDED PRECEDING and current row ) AS current_sum FROM Product;

SELECT product_id, product_name, product_type, sale_price, SUM(sale_price) OVER ( ORDER BY sale_price ) AS current_sum FROM Product; # 上边语句和下边语句结果相同 SELECT product_id, product_name, product_type, sale_price, SUM(sale_price) OVER ( ORDER BY sale_price range BETWEEN UNBOUNDED PRECEDING and current row ) AS current_sum FROM Product;

注:默认框架为 range BETWEEN UNBOUNDED PRECEDING and current row,row和range的区别是rows按照行进行计算,如当求第一行的时候,求和为第一行-第一行,当求第二行的时候,求和为第一行-第二行;而range是按照值进行计算,如sale_price, 当sale_price=100,求和范围为100-100,当sale_price=500,求和范围为100-500。

SELECT product_id, product_name, product_type, sale_price, SUM(sale_price) OVER ( ORDER BY sale_price rows BETWEEN UNBOUNDED PRECEDING and current row ) AS current_sum FROM Product;

MIN、MAX、AVG、COUNT

SELECT product_id, product_name, product_type, sale_price, MIN(sale_price) OVER ( PARTITION BY product_type ORDER BY sale_price  ) AS current_min, MAX(sale_price) OVER ( PARTITION BY product_type ORDER BY sale_price  ) AS current_max, AVG(sale_price) OVER ( PARTITION BY product_type ORDER BY sale_price  ) AS current_avg, COUNT(sale_price) OVER ( PARTITION BY product_type ORDER BY sale_price  ) AS current_count FROM Product;

注:默认框架为range BETWEEN UNBOUNDED PRECEDING and current row*,range是按照值进行计算的,以count来进行讲述,第一组第一行count计算的范围为sale_price值,就是100-100的就一个值,计数1;第一组第二行count计算的范围为100-500,计数2;第二组第一行count计算的范围为500-500,计数2。后续类似。

2)专用窗口函数

RANK、DENSE_RANK、ROW_NUMBER

SELECT product_id, product_name, product_type, sale_price, rank() OVER ( PARTITION BY product_type ORDER BY sale_price rows BETWEEN 2 PRECEDING and current row ) AS current_rk, dense_rank() OVER ( PARTITION BY product_type ORDER BY sale_price  ) AS current_drk, row_number() OVER ( PARTITION BY product_type ORDER BY sale_price  ) AS current_rn FROM Product;

注:rank函数排序是可以跳跃的,dense_rank函数排序是顺序的,row_number函数排序是按照行数。

FIRST_VALUE、LAST_VALUE

SELECT product_id, product_name, product_type, sale_price, FIRST_VALUE(sale_price) OVER ( PARTITION BY product_type ORDER BY sale_price  ) AS current_FV, LAST_VALUE(sale_price) OVER ( PARTITION BY product_type ORDER BY sale_price  ) AS current_LV FROM Product;

LAG 、LEAD。

SELECT product_id, product_name, product_type, sale_price, LAG(sale_price,1) OVER ( PARTITION BY product_type ORDER BY sale_price  ) AS current_LAG, LEAD(sale_price,1) OVER ( PARTITION BY product_type ORDER BY sale_price  ) AS current_LEAD FROM Product;

总结
窗口函数兼具GROUP BY 子句的分组功能和ORDER BY子句的排序功能,但是PARTITION BY子句跟GROUP BY 不具备汇总功能,也就说PARTITION BY子句不会减少行数。

通过PARTITION BY 分组后的记录集合称为窗口。此处的窗口并非“窗户”的意思,而是代表范围。这也是“窗口函数”名称的由来。

一、hive窗口函数语法

在前言中我们已经说了avg()、sum()、max()、min()是分析函数,而over()才是窗口函数,下面我们来看看over()窗口函数的语法结构、及常与over()一起使用的分析函数

1、over()窗口函数的语法结构
2、常与over()一起使用的分析函数
3、窗口函数总结

1、over()窗口函数的语法结构

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

over()函数中包括三个函数:包括分区partition by 列名、排序order by 列名、指定窗口范围rows between 开始位置 and 结束位置。我们在使用over()窗口函数时,over()函数中的这三个函数可组合使用也可以不使用。

over()函数中如果不使用这三个函数,窗口大小是针对查询产生的所有数据,如果指定了分区,窗口大小是针对每个分区的数据。

1.1、over()函数中的三个函数讲解

order by

order by是排序的意思,是该窗口中的

A、partition by

partition by可理解为group by 分组。over(partition by 列名)搭配分析函数时,分析函数按照每一组每一组的数据进行计算的。

B、rows between 开始位置 and 结束位置

是指定窗口范围,比如第一行到当前行。而这个范围是随着数据变化的。over(rows between 开始位置 and 结束位置)搭配分析函数时,分析函数按照这个范围进行计算的。

窗口范围说明:

我们常使用的窗口范围是ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW(表示从起点到当前行),常用该窗口来计算累加。

PRECEDING:往前
FOLLOWING:往后
CURRENT ROW:当前行
UNBOUNDED:起点(一般结合PRECEDING,FOLLOWING使用)
UNBOUNDED PRECEDING 表示该窗口最前面的行(起点)
UNBOUNDED FOLLOWING:表示该窗口最后面的行(终点)
比如说:
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW(表示从起点到当前行)
ROWS BETWEEN 2 PRECEDING AND 1 FOLLOWING(表示往前2行到往后1行)
ROWS BETWEEN 2 PRECEDING AND 1 CURRENT ROW(表示往前2行到当前行)
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING(表示当前行到终点)

2、常与over()一起使用的分析函数:

2.1、聚合类

avg()、sum()、max()、min()

2.1、排名类

row_number()按照值排序时产生一个自增编号,不会重复(如:1、2、3、4、5、6)

rank() 按照值排序时产生一个自增编号,值相等时会重复,会产生空位(如:1、2、3、3、3、6)

dense_rank() 按照值排序时产生一个自增编号,值相等时会重复,不会产生空位(如:1、2、3、3、3、4)

2.1、其他类

lag(列名,往前的行数,[行数为null时的默认值,不指定为null]),以计算用户上次购买时间,或者用户下次购买时间。

lead(列名,往后的行数,[行数为null时的默认值,不指定为null])

ntile(n) 把有序分区中的行分发到指定数据的组中,各个组有编号,编号从1开始,对于每一行,ntile返回此行所属的组的编号

3、窗口函数总结:

其实窗口函数逻辑比较绕,我们可以把窗口理解为对表中的数据进行分组,排序等计算。

 
 
 
 
 
 

含义:窗口函数也叫OLAP函数(Online Anallytical Processing,联机分析处理),可以对数据进行实时分析处理。

作用:

  • 解决排名问题,e.g.每个班级按成绩排名
  • 解决TOPN问题,e.g.每个班级前两名的学生

语法:

select 窗口函数 over (partition by 用于分组的列名, order by 用于排序的列名

分类:

  • 专用窗口函数:rank(),dense_rank(),row_number()
  • 汇总函数:max(),min(),count(),sum(),avg()

注意:窗口函数是对where后者group by子句处理后的结果进行操作,因此按照SQL语句的运行顺序,窗口函数一般放在select子句中。

窗口函数的用法

    1. 专用窗口函数

rank()函数

说明

  • rank()是排序函数,括号中不需要有参数;
  • 通过partition by将班级分类,相当于之前用过的group by子句功能,但是group by子句分类汇总会改变原数据的行数,而用窗口函数自救保持原行数;
  • 通过order by将成绩降序排列,与之前学的order by子句用法一样,后边可以升序asc或者降序desc;

总结:

  • 窗口函数这里的“窗口”表示范围,可以理解为将原数据划分范围,即分组,然后用函数实现某些目的
  • 窗口函数有分组和排序的功能
  • 不减少原表的行数

2. 其他专用窗口函数:dense_rank/row_number

  • 用法与rank()函数相同

  • 当成绩相同时,会存在并列的情况,主要区别是三个函数如何处理并列情况:

在rank()函数,如果有并列情况,会占用下一个名次的位置,比如,成绩为100的学生有三个并列第一,那么99分的学生是第二名,通过rank()函数,名次是:1,1,1,4;

在dense()函数中,如果有并列的情况,不会占用下一个名词,同用上个例子,名次是:1,1,1,2;

在row_number()函数中,会忽略并列的情况,同用上述例子,名次是:1,2,3,4;

 

mysql窗口函数的更多相关文章

  1. MySQL 窗口函数

    1. 窗口函数概念和语法 窗口函数对一组查询行执行类似聚合的操作.然而,聚合操作将查询行分组到单个结果行,而窗口函数为每个查询行产生一个结果: 函数求值发生的行称为当前行 与发生函数求值的当前行相关的 ...

  2. MySQL 8.0窗口函数

    团队介绍 网易乐得DBA组,负责网易乐得电商.网易邮箱.网易技术部数据库日常运维,负责数据库私有云平台的开发和维护,负责数据库及数据库中间件Cetus的开发和测试等等. 一.窗口函数的使用场景 作为I ...

  3. 使用MySQL会话变量实现窗口函数

    一.MySQL窗口函数 (1) 序号函数 row_number()在相等的两条记录上随机排序,但序号按照1.2递增,然后后面的序号继续递增为3,中间不会产生序号间隙: rank()/dense_ran ...

  4. MySQL 8.0 新增SQL语法对窗口函数和CTE的支持

    尝试了一下MySQL 8.0的部分新特性. 如果用过MSSQL或者是Oracle中的窗口函数(Oracle中叫分析函数), 然后再使用MySQL 8.0之前的时候,就知道需要在使用窗口函数处理逻辑的痛 ...

  5. 窗口函数解决数据岛问题(mysql暂无窗口函数,可以通过用户变量解决窗口函数问题)

    数据岛问题: 有表: create table dataisland (id int)  insert into  dataisland values(1),(2),(3),(7),(11),(12) ...

  6. dense_rank()和rank() 窗口函数 mysql

    dense_rank()的语法 DENSE_RANK() OVER ( PARTITION BY <expression>[{,<expression>...}] ORDER ...

  7. 从Oracle迁移到Mysql之前必须知道的50件事

    1. 对子查询的优化表现不佳. 2. 对复杂查询的处理较弱 3. 查询优化器不够成熟 4. 性能优化工具与度量信息不足 5. 审计功能相对较弱 6. 安全功能不成熟,甚至可以说很粗糙.没有用户组与角色 ...

  8. 数据库(MSSQLServer,Oracle,DB2,MySql)常见语句以及问题

    创建数据库表 create table person ( FName varchar(), FAge int, FRemark varchar(), primary key(FName) ) 基本sq ...

  9. PostgreSQL与MySQL比较(转)

    Mysql 使用太广泛了,以至于我不得不将一些应用从mysql 迁移到postgresql, 很多开源软件都是以Mysql 作为数据库标准,并且以Mysql 作为抽象基础的,但是具体使用过程中,发现M ...

  10. What's New In MySQL 8.0

        由于8.0内有很多C++11特性.需要gcc4.8版本以上.Rhel6系列默认gcc是4.7.在安装gcc6.1之后仍然检查不过. 原因可能是6.1版本不一定高于4.7,暂不讨论.鉴于升级gc ...

随机推荐

  1. node.js接收前端上传的文件并保存到其他位置+后端代码支持进度条

    一:直接上传文件,放入body里 1.前端代码 <input type="file" onchange="sendFiles(this.files)"&g ...

  2. Python语法与基本数据类型

    Python语法与基本数据类型 一.Python语法之注释 1.注释 注释就是对一段代码的解释说明 2.注释的写法 1.单行注释:解释说明的文字前面加#号, pycharm中有快捷键 ctrl+? 2 ...

  3. NodeJS 实战系列:DevOps 尚未解决的问题

    本文将通过展示 NodeJS 应用里环境变量的提取过程,来一窥 DevOps 技术是如何应用在现在云平台上的运维工作中的.同时我也想让大家在这里看到 DevOps 的另外一面,即它并非全能,从本地开发 ...

  4. CentOS7 RPM方式安装JDK

    1.下载jdk rpm Java Downloads | Oracle 中国 https://www.oracle.com/cn/java/technologies/downloads/#jdk19- ...

  5. IDEA插件:lombok

    1 安装插件lombok File => Settings => Plugins => Marketplace.在 Marketplace 中搜索 lombok 并安装,安装成功后 ...

  6. 亲测有效! Super PhotoCut Pro 超级抠图工具 V2.8.8 for mac 破解版

    亲测有效! Super PhotoCut Pro 超级抠图工具 V2.8.8 for mac  破解版 Super PhotoCut 是一款专业的,非常易于使用的图片抠图工具.它能够准确地覆盖你想要去 ...

  7. H5商城项目源码 (可预览 测试有效)

    商城简介 这个商城项目由首页模块,发现模块,购物车模块以及我的等四大模块组成了33个相关内容界面 预览下载直通车 预览地址 首页模块 首页拥有搜索模块.分类模块.内容模块组成 发现模块 发现模块主要是 ...

  8. 1 - 【RocketMQ 系列】CentOS 7.6 安装部署RocketMQ

    一.前置准备工作 CentOS 7.6 安装 jdk1.8 openjdk 1.查看JDK版本 yum search java|grep jdk 2.安装jdk1.8,安装默认的目录为: /usr/l ...

  9. TCP/IP协议(3): Wi-Fi(IEEE 802.11) 协议 —— 构成无线局域网的基本协议

    TCP/IP协议(3): Wi-Fi(IEEE 802.11) 协议 -- 构成无线局域网的基本协议 关于 Wi-Fi(IEEE 802.11) 协议 关于 IEEE 802.11 IEEE 802. ...

  10. python下载图片实现方法

    转载: https://www.jb51.net/article/119178.htm