mysql窗口函数
使用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子句中。
窗口函数的用法
- 专用窗口函数
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窗口函数的更多相关文章
- MySQL 窗口函数
1. 窗口函数概念和语法 窗口函数对一组查询行执行类似聚合的操作.然而,聚合操作将查询行分组到单个结果行,而窗口函数为每个查询行产生一个结果: 函数求值发生的行称为当前行 与发生函数求值的当前行相关的 ...
- MySQL 8.0窗口函数
团队介绍 网易乐得DBA组,负责网易乐得电商.网易邮箱.网易技术部数据库日常运维,负责数据库私有云平台的开发和维护,负责数据库及数据库中间件Cetus的开发和测试等等. 一.窗口函数的使用场景 作为I ...
- 使用MySQL会话变量实现窗口函数
一.MySQL窗口函数 (1) 序号函数 row_number()在相等的两条记录上随机排序,但序号按照1.2递增,然后后面的序号继续递增为3,中间不会产生序号间隙: rank()/dense_ran ...
- MySQL 8.0 新增SQL语法对窗口函数和CTE的支持
尝试了一下MySQL 8.0的部分新特性. 如果用过MSSQL或者是Oracle中的窗口函数(Oracle中叫分析函数), 然后再使用MySQL 8.0之前的时候,就知道需要在使用窗口函数处理逻辑的痛 ...
- 窗口函数解决数据岛问题(mysql暂无窗口函数,可以通过用户变量解决窗口函数问题)
数据岛问题: 有表: create table dataisland (id int) insert into dataisland values(1),(2),(3),(7),(11),(12) ...
- dense_rank()和rank() 窗口函数 mysql
dense_rank()的语法 DENSE_RANK() OVER ( PARTITION BY <expression>[{,<expression>...}] ORDER ...
- 从Oracle迁移到Mysql之前必须知道的50件事
1. 对子查询的优化表现不佳. 2. 对复杂查询的处理较弱 3. 查询优化器不够成熟 4. 性能优化工具与度量信息不足 5. 审计功能相对较弱 6. 安全功能不成熟,甚至可以说很粗糙.没有用户组与角色 ...
- 数据库(MSSQLServer,Oracle,DB2,MySql)常见语句以及问题
创建数据库表 create table person ( FName varchar(), FAge int, FRemark varchar(), primary key(FName) ) 基本sq ...
- PostgreSQL与MySQL比较(转)
Mysql 使用太广泛了,以至于我不得不将一些应用从mysql 迁移到postgresql, 很多开源软件都是以Mysql 作为数据库标准,并且以Mysql 作为抽象基础的,但是具体使用过程中,发现M ...
- What's New In MySQL 8.0
由于8.0内有很多C++11特性.需要gcc4.8版本以上.Rhel6系列默认gcc是4.7.在安装gcc6.1之后仍然检查不过. 原因可能是6.1版本不一定高于4.7,暂不讨论.鉴于升级gc ...
随机推荐
- GraalVM和Spring Native尝鲜,一步步让Springboot启动飞起来,66ms完成启动
简介 GraalVM是高性能的JDK,支持Java/Python/JavaScript等语言.它可以让Java变成二进制文件来执行,让程序在任何地方运行更快.这或许是Java与Go的一场战争? 下载安 ...
- Python解释器下载与安装
Python解释器下载与安装 一.Python解释器 1.Python的发展方向 web方向,自动化运维,自动化测试,自动化办公,网络爬虫,金融量化,人工智能,机器学习,数据分析 2.Python解释 ...
- Java 进阶P-8.1+P-8.2
捕捉异常 异常的处理方式之一:捕获异常 捕获异常是通过3个关键词来实现的:try-catch-finally.用try来执行一段程序,如果出现异常,系统抛出一个异常,可以通过它的类型来捕捉(catch ...
- Unity3D——鼠标双击
Unity之鼠标双击 小黑终于又回到公司了! 能在公司安生的待段时间了,今天更新一篇吧! 懒惰的小黑给大家分享个好东西吧,解决双击之痛! 前言 小黑相信有许多人和我一样.万年不会碰到一个需求:双击!可 ...
- 11月30日内容总结——前端简介、http协议概念、html协议概念及基础知识和部分标签的讲解
目录 一.前端与后端的概念 什么是前端开发? 什么是后端? 学习前端的目的 前端三剑客 二.前端前戏 三.HTTP协议 1.四大特性 2.报文格式 3.响应状态码 四.HTML概览 1.HTML简介 ...
- python判断密码连续,重复,大小写、数字、符号混合密码复杂度要求
一.python 判断密码连续,重复,大小写.数字.符号混合密码复杂度要求 1. 运行环境 python 3.6.8 2. 密码必须包含大小写.数字.特殊符号中的3种且长度为8-16位 def ver ...
- Zstack私有云平台运行实践
很高兴昨天加了大名鼎鼎的杰杰站长的微信,系统运行的怎么样,一定不能只是给力两个字完事,下面就上具体的: 经过这几年的运行费和预研经费的支持,组里除了在线的几台服务器外,慢慢离线也积攒了几台用作调试和做 ...
- 【USACO 2021 January Contest, Platinum】Problem 1. Sum of Distances
\(\text{Solution}\) 一个性质:两个 \(K\) 元组有边相连当且仅当每个点在对应的图中到 \(1\) 有奇偶性相同的路径 那么我们就可以预处理每个图中的点到 \(1\) 的奇偶最短 ...
- Vue 计算属性与普通的函数有什么区别?
计算属性的优势 计算属性的作用是计算复杂的逻辑,并返回一个结果,提供给模板多次使用:只要依赖的响应式数据没有改变,计算属性就不会重新执行,而是直接返回它存储的缓存.所以,节省不必要的开销. 模板语法的 ...
- mac系统上hdfs java api的简单使用
目录 1.背景 2.环境准备 3.环境搭建 3.1 引入jar包 3.2 引入log4j.properties配置文件 3.3 初始化Hadoop Api 4.java api操作 4.1 创建目录 ...