SQL学习笔记——task05:SQL高级处理
文章目录
- 前言
- 1. 窗口函数
- 1.1 窗口函数概念及基本的使用方法
- 2. 窗口函数种类
- 2.1 专用窗口函数
- 2.2 聚合函数在窗口函数上的使用
- 3. 窗口函数的应用 - 计算移动平均
- 3.1 窗口函数适用的范围和注意事项
- 4. GROUPING 运算符
- 4.1 ROLLUP -计算合计及小计
- 练习题
- 总结
前言
在日常工作中,经常会遇到需要在每组内排名,比如下面的业务需求:
- 排名问题:每个部门按业绩来排名;
- topN问题:找出每个部门排名前N的员工进行奖励。
面对这类需求,就需要使用sql的高级功能窗口函数了。
1. 窗口函数
1.1 窗口函数概念及基本的使用方法
窗口函数也称为OLAP函数。OLAP 是OnLine AnalyticalProcessing 的简称,意思是对数据库数据进行实时分析处理。
为了便于理解,称之为窗口函数。常规的SELECT语句都是对整张表进行查询,而窗口函数可以让我们有选择的去某一部分数据进行汇总、计算和排序。
窗口函数的通用形式:
<窗口函数> OVER ([PARTITION BY <列名>]ORDER BY <排序用列名>)
其中的*[] 中的内容可以省略。
窗口函数最关键的的是搞明白关键字PARTITION BY 和ORDER BY 的作用。
PARTITON BY是用来分组,即选择要看哪个窗口,类似于GROUP BY 子句的分组功能,但是PARTITION BY 子句并不具备GROUP BY 子句的汇总功能,并不会改变原始表中记录的行数。
ORDER BY是用来排序,即决定窗口内,是按那种规则(字段)来排序的。
举个例子:
SELECT product_name,product_type,sale_price,RANK() OVER (PARTITION BY product_typeORDER BY sale_price) AS rankingFORM product
得到的结果:
先忽略生成的新列 - [ranking], 看下原始数据在PARTITION BY 和 ORDER BY 关键字的作用下发生了什么变化。
PARTITION BY 能够设定窗口对象范围。本例中,为了按照商品种类进行排序,我们指定了product_type。即一个商品种类就是一个小的"窗口"。
ORDER BY 能够指定按照哪一列、何种顺序进行排序。为了按照销售单价的升序进行排列,我们指定了sale_price。此外,窗口函数中的ORDER BY与SELECT语句末尾的ORDER BY一样,可以通过关键字ASC/DESC来指定升序/降序。省略该关键字时会默认按照ASC,也就是升序进行排序。
2. 窗口函数种类
大致来说,窗口函数可以分为两类。
- 将SUM、MAX、MIN等聚合函数用在窗口函数中;
- RANK、DENSE_RANK等排序用的专用窗口函数。
2.1 专用窗口函数
RANK函数
计算排序时,如果存在相同位次的记录,则会跳过之后的位次。(例)有3条记录排在第1位时:1位、1位、1位、4位…DENSE_RANK函数
同样是计算排序,即使存在相同位次的记录,也不会跳过之后的位次。(例)有3条记录排在第1位时:1位、1位、1位、2位…ROW_NUMBER函数
同样是计算排序,即使存在相同位次的记录,也不会跳过之后的位次。(例)有3条记录排在第1位时:1位、2位、3位、4位。
运行以下代码:
SELECT product_name,product_type,sale_price,RANK() OVER (ORDER BY sale_price) AS ranking,DENSE_RANK() OVER (ORDER BY sale_price) AS dense_ranking,ROW_NUMBER() OVER (ORDER BY sale_price) AS row_numFROM product
执行结果:
2.2 聚合函数在窗口函数上的使用
聚合函数在窗口函数中的使用方法和之前的专用窗口函数一样,只是出来的结果是一个累计的聚合函数值。
运行以下代码:
SELECT product_id,product_name,sale_price,SUM(sale_price) OVER (ORDER BY product_id) AS current_sum,AVG(sale_price) OVER (ORDER BY product_id) AS current_avgFROM product;
执行结果:
执行结果:
可以看出,聚合函数结果是,按我们指定的排序,这里是product_id,当前所在行及之前所有的行的合计或均值。即累计到当前的聚合。
3. 窗口函数的应用 - 计算移动平均
在上面提到,聚合函数在窗口函数使用时,计算的是累积到当前行的所有的数据的聚合。实际上,还可以指定更加详细的汇总范围。该汇总范围称为框架(frame)。
语法:
<窗口函数> OVER (ORDER BY <排序用列名>ROWS n PRECEDING)<窗口函数> OVER (ORDER BY <排序用列名>ROWS BETWEEN n PRECEDING AND n FOLLOWING)
- PRECEDING (“之前”),将框架指定为“截止到之前n行”,加上自身行;
- FOLLOWING (“之后”),将框架指定为“截止到之后n行”,加上自身行。
BETWEEN 1 PRECEDING AND 1 FOLLOWING,将框架指定为“之前1行”+“之后1行”
执行以下代码:
SELECT product_id,product_name,sale_price,AVG(sale_price) OVER (ORDER BY product_idROWS 2 PRECEDING) AS moving_avg,AVG(sale_price) OVER (ORDER BY product_idROWS BETWEEN 1 PRECEDINGAND 1 FOLLOWING) AS moving_avgFROM product
执行结果:
注意观察框架的范围。
ROWS 2 PRCEDING:
ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING:
3.1 窗口函数适用的范围和注意事项
- 原则上,窗口函数只能在SELECT 子句中使用
- 窗口函数OVER 中的ORDER BY 子句并不会影响最终结果的排序。其只是用来决定窗口函数按何种顺序计算
4. GROUPING 运算符
4.1 ROLLUP -计算合计及小计
常规的GROUP BY 只能得到每个分类的小计,有时候还需要计算分类的合计,可以用ROLLUP 关键字。
SELECT product_type,regist_date,SUM(sale_price) AS sum_priceFROM product
GROUP BY product_type, regist_date WITH ROLLUP
得到的结果为:
这里ROLLUP 对product_type, regist_date两列进行合计汇总。结果实际上有三层聚合,如下图模块3是常规的 GROUP BY的结果,需要注意的是衣服 有个注册日期为空的,这是本来数据就存在日期为空的,不是对衣服类别的合计;模块2和1 ROLLUP 带来的合计,模块2是对产品种类的合计,模块1是对全部数据的统计。
ROLLUP 可以对多列进行汇总小计和合计。
练习题
练习1:
说一下使用的 product(商品)表执行如下 SELECT 语句所能得到的结果。
SELECT product_id,product_name,sale_price,MAX(sale_price) OVER (ORDER BY product_id) AS Current_max_priceFROM product
运行结果:
练习2:
继续使用product 表,计算出按照登记日期(registe_date )升序进行排列的各日期的销售单价(sale_price)的总额。排序是需要将登记日期为NULL 的“运动T恤”记录排在第1位(也就是将其看作比其他日期都早)。
SELECT product_id,product_name,regist_date,SUM(sale_price) OVER (partition by regist_date) AS sum_price_by_dateFROM product
ORDER BY -ISNULL(regist_date), regist_date;
运行结果:
练习3 思考题:
- Q:窗口函数不指定RARTITION BY 的效果是什么?
A: 1. 窗口函数具有以下功能:
1)同时具有分组(partition by)和排序(order by)的功能;
2)不减少原表的行数,所以经常用来在每组内排名。
如果不指定PARTITION BY的话,窗口函数的操作窗口就是整个表(即所有记录都算为同一个分组)。
- Q:为什么窗口函数只能在SELECT 子句使用? 实际上,在ORDER BY 子句使用系统并不会报错。
A:因为窗口函数是对where或者group by子句处理后的结果进行操作,所以窗口函数原则上只能写在select子句中;而ORDER BY 子句则是对SELECT 子句中的结果进行操作,操作的是整个结果表,所以可以使用窗口函数,但是窗口函数的返回结果只作为ORDER BY子句的排序依据,并不能返回期望的结果。
总结
- 窗口函数语法:
<窗口函数> over (partition by <用于分组的列名>order by <用于排序的列名>)
<窗口函数>的位置,可以放以下两种函数:
- 专用窗口函数,比如rank, dense_rank, row_number等
- 聚合函数,如sum. avg, count, max, min等
- 窗口函数有以下功能:
- 同时具有分组(partition by)和排序(order by)的功能
- 不减少原表的行数,所以经常用来在每组内排名
- 窗口函数的使用场景:
业务需求 “在每组内排名”,比如:
- 排名问题:每个部门按业绩来排名
- topN问题:找出每个部门排名前N的员工进行奖励
SQL学习笔记——task05:SQL高级处理相关推荐
- SQL学习笔记 | 02 SQL语句结构
SQL学习笔记 | 02 SQL语句结构 一.表的导入 1.表的命名 2.导入步骤 3.导入需注意 二.标准SQL语法 1.语句结构 2.数据表的其他关键词 3.SQL语句的分类 一.表的导入 1.表 ...
- Spark学习笔记(7)---Spark SQL学习笔记
Spark SQL学习笔记 Spark SQL学习笔记设计到很多代码操作,所以就放在github, https://github.com/yangtong123/RoadOfStudySpark/bl ...
- 判断题:oracle自带的sql语言环境是pl/sql,Oracle之PL/SQL学习笔记之数据类型(三)
Oracle之PL/SQL学习笔记之数据类型(三) 所有的编程语言中变量是使用最频繁的.PL/SQL作为一个面向过程的数据库编程语言同样少不了变量,利用变量可以把PL/SQL块需要的参数传递进来,做到 ...
- Oracle之PL/SQL学习笔记之有名块练习
2019独角兽企业重金招聘Python工程师标准>>> Oracle之PL/SQL学习笔记之有名块练习 存储过程案例: 案例1: 根据雇员姓名跟新雇员工资,如果雇员不存在输出没有该雇 ...
- 【LittleXi】sql学习笔记
[LittleXi]sql学习笔记 数据类型 INT 整数型 VARCHAR 字符串 DECIMAL(a,b) 浮点型(a代表位数,b代表小数位位数) BLOB 图片.影片.档案 DATA 日期 XX ...
- 探针一号的SQL学习笔记
SQL学习笔记 文章目录 SQL学习笔记 1.问题 2.SQL基本语句 3.SQL基本数据查询 4.SQL复杂点的数据查询 5.DML操作 6.数据表操作 1.问题 什么是数据库? 是一个仓库,可以按 ...
- SQL学习笔记_Aliyun4
SQL学习笔记_Aliyun4 本笔记为阿里云天池龙珠计划SQL训练营的学习内容,链接为:https://tianchi.aliyun.com/specials/promotion/aicampsql ...
- 简简单单 My SQL 学习笔记(2)——分组和简单数据的查询
初始数据 创建表(要记得先选择好我们的数据库 use+数据库名) create table student( studentno int(4) primary key not null auto_in ...
- SQL学习笔记之二:QUOTENAME函数
SQL学习笔记之二:QUOTENAME函数 --SQL学习笔记二 --函数QUOTENAME --功能:返回带有分隔符的Unicode 字符串,分隔符的加入可使输入的字符串成为有效的Microsoft ...
最新文章
- HTML里面设置文本倒影,文字倒影怎么做
- 全站HTTPS简单实践
- vc mysql utf8_C/C++ 连接 MySQL (VC 版)
- java.lang.IllegalArgumentException: pointerIndex out of range
- AOP与OOP的区别
- ant设置国际化设置为中文
- luci L大_智慧城市大讲堂 l 大咖说5G智慧大交通
- 什么是IDS/IPS?
- Python 快速部署安装所需模块
- Linux 下子线程 exit code 在主线程中的使用
- Create VerifyCode by jsp of java
- html swf转mp4,《swf转换成mp4及高清视频的方法》.docx
- 快乐牛牛终极板creator1.82 shader 挫牌代码
- java opts tomcat,tomcat JAVA_OPTS配备
- 关于Snoop的用法
- 计算机桌面颜色比较暗,电脑显示器颜色偏暗怎么回事
- 《Jira实战》作者王杰-使用Jira打造精益敏捷的交付能力
- 数字图像处理(15): 灰度直方图(matplotlib 和OpenCV 绘制直方图)
- mysql的print用法_e.printStackTrace();和log.error()的区别和用法
- 关于系统检测到您机器上没有启动QQ的解决方法
热门文章
- mtk电池曲线测试(1)--分容测试
- 博客马拉松|和 OpenMLDB 一路向前
- 对于thtd标签colspan不起作用的问题
- html 输出php_php怎么输出html源代码
- Alienware 17 R4安装windows10与ubuntu16.04双系统
- Unity精华☀️ 面试官眼中的「设计模式」
- 沙盒软件-软件多开-命令行-运行参数-进程通信-运行和评估
- 为什么 Pr 中添加的文字很模糊?
- CFA课程打卡-2019.11.25
- php用根证书生成客户端证书,OPENSSL根证书的生成及使用