文章目录

  • 前言
  • 1. 窗口函数
    • 1.1 窗口函数概念及基本的使用方法
  • 2. 窗口函数种类
    • 2.1 专用窗口函数
    • 2.2 聚合函数在窗口函数上的使用
  • 3. 窗口函数的应用 - 计算移动平均
    • 3.1 窗口函数适用的范围和注意事项
  • 4. GROUPING 运算符
    • 4.1 ROLLUP -计算合计及小计
  • 练习题
  • 总结

前言

在日常工作中,经常会遇到需要在每组内排名,比如下面的业务需求:

  1. 排名问题:每个部门按业绩来排名;
  2. topN问题:找出每个部门排名前N的员工进行奖励。

面对这类需求,就需要使用sql的高级功能窗口函数了。


1. 窗口函数

1.1 窗口函数概念及基本的使用方法

窗口函数也称为OLAP函数。OLAP 是OnLine AnalyticalProcessing 的简称,意思是对数据库数据进行实时分析处理。

为了便于理解,称之为窗口函数。常规的SELECT语句都是对整张表进行查询,而窗口函数可以让我们有选择的去某一部分数据进行汇总、计算和排序。

窗口函数的通用形式:

<窗口函数> OVER ([PARTITION BY <列名>]ORDER BY <排序用列名>)

其中的*[] 中的内容可以省略。
窗口函数最关键的的是搞明白关键字PARTITION BYORDER 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. 窗口函数种类

大致来说,窗口函数可以分为两类。

  1. 将SUM、MAX、MIN等聚合函数用在窗口函数中;
  2. 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)
  1. PRECEDING (“之前”),将框架指定为“截止到之前n行”,加上自身行;
  2. 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 思考题:

  1. Q:窗口函数不指定RARTITION BY 的效果是什么?

A: 1. 窗口函数具有以下功能:
1)同时具有分组(partition by)和排序(order by)的功能;
2)不减少原表的行数,所以经常用来在每组内排名。
如果不指定PARTITION BY的话,窗口函数的操作窗口就是整个表(即所有记录都算为同一个分组)。

  1. Q:为什么窗口函数只能在SELECT 子句使用? 实际上,在ORDER BY 子句使用系统并不会报错。

A:因为窗口函数是对where或者group by子句处理后的结果进行操作,所以窗口函数原则上只能写在select子句中;而ORDER BY 子句则是对SELECT 子句中的结果进行操作,操作的是整个结果表,所以可以使用窗口函数,但是窗口函数的返回结果只作为ORDER BY子句的排序依据,并不能返回期望的结果。


总结

  1. 窗口函数语法:
<窗口函数> over (partition by <用于分组的列名>order by <用于排序的列名>)

<窗口函数>的位置,可以放以下两种函数:

  • 专用窗口函数,比如rank, dense_rank, row_number等
  • 聚合函数,如sum. avg, count, max, min等
  1. 窗口函数有以下功能:
  • 同时具有分组(partition by)和排序(order by)的功能
  • 不减少原表的行数,所以经常用来在每组内排名
  1. 窗口函数的使用场景:

业务需求 “在每组内排名”,比如:

  • 排名问题:每个部门按业绩来排名
  • topN问题:找出每个部门排名前N的员工进行奖励

SQL学习笔记——task05:SQL高级处理相关推荐

  1. SQL学习笔记 | 02 SQL语句结构

    SQL学习笔记 | 02 SQL语句结构 一.表的导入 1.表的命名 2.导入步骤 3.导入需注意 二.标准SQL语法 1.语句结构 2.数据表的其他关键词 3.SQL语句的分类 一.表的导入 1.表 ...

  2. Spark学习笔记(7)---Spark SQL学习笔记

    Spark SQL学习笔记 Spark SQL学习笔记设计到很多代码操作,所以就放在github, https://github.com/yangtong123/RoadOfStudySpark/bl ...

  3. 判断题:oracle自带的sql语言环境是pl/sql,Oracle之PL/SQL学习笔记之数据类型(三)

    Oracle之PL/SQL学习笔记之数据类型(三) 所有的编程语言中变量是使用最频繁的.PL/SQL作为一个面向过程的数据库编程语言同样少不了变量,利用变量可以把PL/SQL块需要的参数传递进来,做到 ...

  4. Oracle之PL/SQL学习笔记之有名块练习

    2019独角兽企业重金招聘Python工程师标准>>> Oracle之PL/SQL学习笔记之有名块练习 存储过程案例: 案例1: 根据雇员姓名跟新雇员工资,如果雇员不存在输出没有该雇 ...

  5. 【LittleXi】sql学习笔记

    [LittleXi]sql学习笔记 数据类型 INT 整数型 VARCHAR 字符串 DECIMAL(a,b) 浮点型(a代表位数,b代表小数位位数) BLOB 图片.影片.档案 DATA 日期 XX ...

  6. 探针一号的SQL学习笔记

    SQL学习笔记 文章目录 SQL学习笔记 1.问题 2.SQL基本语句 3.SQL基本数据查询 4.SQL复杂点的数据查询 5.DML操作 6.数据表操作 1.问题 什么是数据库? 是一个仓库,可以按 ...

  7. SQL学习笔记_Aliyun4

    SQL学习笔记_Aliyun4 本笔记为阿里云天池龙珠计划SQL训练营的学习内容,链接为:https://tianchi.aliyun.com/specials/promotion/aicampsql ...

  8. 简简单单 My SQL 学习笔记(2)——分组和简单数据的查询

    初始数据 创建表(要记得先选择好我们的数据库 use+数据库名) create table student( studentno int(4) primary key not null auto_in ...

  9. SQL学习笔记之二:QUOTENAME函数

    SQL学习笔记之二:QUOTENAME函数 --SQL学习笔记二 --函数QUOTENAME --功能:返回带有分隔符的Unicode 字符串,分隔符的加入可使输入的字符串成为有效的Microsoft ...

最新文章

  1. HTML里面设置文本倒影,文字倒影怎么做
  2. 全站HTTPS简单实践
  3. vc mysql utf8_C/C++ 连接 MySQL (VC 版)
  4. java.lang.IllegalArgumentException: pointerIndex out of range
  5. AOP与OOP的区别
  6. ant设置国际化设置为中文
  7. luci L大_智慧城市大讲堂 l 大咖说5G智慧大交通
  8. 什么是IDS/IPS?
  9. Python 快速部署安装所需模块
  10. Linux 下子线程 exit code 在主线程中的使用
  11. Create VerifyCode by jsp of java
  12. html swf转mp4,《swf转换成mp4及高清视频的方法》.docx
  13. 快乐牛牛终极板creator1.82 shader 挫牌代码
  14. java opts tomcat,tomcat JAVA_OPTS配备
  15. 关于Snoop的用法
  16. 计算机桌面颜色比较暗,电脑显示器颜色偏暗怎么回事
  17. 《Jira实战》作者王杰-使用Jira打造精益敏捷的交付能力
  18. 数字图像处理(15): 灰度直方图(matplotlib 和OpenCV 绘制直方图)
  19. mysql的print用法_e.printStackTrace();和log.error()的区别和用法
  20. 关于系统检测到您机器上没有启动QQ的解决方法

热门文章

  1. mtk电池曲线测试(1)--分容测试
  2. 博客马拉松|和 OpenMLDB 一路向前
  3. 对于thtd标签colspan不起作用的问题
  4. html 输出php_php怎么输出html源代码
  5. Alienware 17 R4安装windows10与ubuntu16.04双系统
  6. Unity精华☀️ 面试官眼中的「设计模式」
  7. 沙盒软件-软件多开-命令行-运行参数-进程通信-运行和评估
  8. 为什么 Pr 中添加的文字很模糊?
  9. CFA课程打卡-2019.11.25
  10. php用根证书生成客户端证书,OPENSSL根证书的生成及使用