1 小时 SQL 极速入门(三)——分析函数
1 小时 SQL 极速入门
前面两篇我们从 SQL 的最基础语法讲起,到表联结多表查询。
大家可以点击链接查看
1 小时 SQL 极速入门(一)
1 小时 SQL 极速入门(二)
今天我们讲一些在做报表和复杂计算时非常实用的分析函数。由于各个数据库函数的实现不太一样,本文基于 Oracle 12c 。
ROW_NUMBER()函数
这个函数在平时用的还是比较多的。这个函数的作用是为分组内的每一行返回一个行号。我们还是举例来说明。
假设我们有以下数据表:

共 8 个订单,分为 A,B,C,D四种类型,后面两列是订单描述和订单数量。
假如我们现在想找到每个订单类型中数量最少的一行记录,比如想找到 A 类型订单数量最少的,B 类型订单数量最少的。。。
我们要怎么写呢 ? 用 GROUP BY 可能会很麻烦。这里用 ROW_NUMBER() 就很合适
SELECT order_no,
order_type,
order_text,
order_qty,
row_number() OVER(PARTITION BY order_type order by order_qty) AS rowno
FROM wip_order_test
结果:

可以看到,每一行最后都有一个从低到高的编号,有了这个编号我们就可以通过取编号为 1 的行来得到每个分组中订单数量最少的一行记录。
解释一下,ROW_NUMBER() 为每一行返回一个行号, partition by 表示分组,这里表示根据 order_type 分组,然后我们按照订单数量排序。就会得到每个分组内的按照订单数量排序的行号。
SUM() OVER()函数
假如我们现在要 查询每个类型的订单总数分别是多少,要怎么做?
大家可能会想到 GROUP BY,不过大家可以自己试试,是否能得到和我同样的结果
SELECT order_no,
order_type,
order_text,
order_qty,
sum(order_qty) OVER(PARTITION BY order_type) AS sum_qty
FROM wip_order_test
结果:

看到后面多了一个数量列,就是每个分组的订单总数量。是不是很方便?
除了 SUM 函数,其他几个计算函数如 AVG(),MAX(),MIN(),COUNT()的使用方法和 SUM 一样。
窗口函数
窗口函数可以对一个结果集内的一定范围内值进行累积,或者通过移动窗口进行累积。还是看例子吧。
SELECT order_no,
order_type,
order_text,
order_qty,
sum(order_qty) OVER
(ORDER BY order_no ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
AS cumulative_qty
FROM wip_order_test;

解释一下:还是用 SUM 来计算总和,这里我们使用了新的语法, ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW 定义了窗口的起点和终点,UNBOUNDED PRECEDING表示起点在第一行,CURRENT ROW 表示终点在当前行。我们看一下上图的结果,能看到最后一列的值是逐行累加的。
移动窗口
上面我们的窗口的起点是固定的,终点逐渐往下移,我们可以创建一个固定大小的窗口,起点和终点同时往下移动。只需要修改 UNBOUNDED 为一个固定的数字就可以了。我们修改成 2, 和 3 分别看一下
SELECT order_no,
order_type,
order_text,
order_qty,
SUM(order_qty) OVER (ORDER BY order_no ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS cumulative_qty2,
SUM(order_qty) OVER (ORDER BY order_no ROWS BETWEEN 3 PRECEDING AND CURRENT ROW) AS cumulative_qty3
FROM wip_order_test;

解释下:倒数第二列我们修改窗口起点2,表示当前行与前两行之间的范围。可以看到每一行的值都是当前行与它前面两行的值的累加。而最后一列,是当前行与它之前3行的值的累加。每处理一行,窗口的起点和终点都向下移动。
同理,SUM 也可以改为 AVG 求窗口的平均值
FIRST_VALUE() 和 LAST_VALUE()可以获取窗口的第一行和最后一行,NTH_VALUE()可以获取第 N 行。看一下例子:
SELECT order_no,
order_type,
order_text,
order_qty,
first_value(order_qty) OVER (ORDER BY order_no ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS first_value,
last_value(order_qty) OVER (ORDER BY order_no ROWS BETWEEN 3 PRECEDING AND CURRENT ROW) AS last_value,
nth_value(order_qty,2) OVER (ORDER BY order_no ROWS BETWEEN 3 PRECEDING AND CURRENT ROW) AS second_value
FROM wip_order_test;

LISTAGG() 函数
这个函数很有用,有时候在 GROUP BY 以后,我们想让分组内的某一列的几个值显示在一行上,比如:
SELECT
order_type,
listagg(to_char(order_text),'-') WITHIN GROUP (ORDER BY order_type) AS text
FROM wip_order_test
GROUP BY order_type
结果:

看到,通过 LISTAGG ,把每个分组中的订单描述字段连接起来。第一个参数表示要合并的字段名字,第二个参数表示分隔符。
TOP-N 查询
Oracle 12c中新增了对 TOP-N的支持。
SELECT order_no,
order_type,
order_text,
order_qty
FROM wip_order_test
FETCH FIRST 3 ROWS ONLY;

我们用 FETCH FIRST 3 取出了前 3 行数据,这里也可以使用 FETCH FIRST 20 PERCENT ROWS ONLY 用百分比来取出前 20% 的数据。
还可以使用 OFFSET 关键字,来表示从第几行开始取,比如 OFFSET 5 ROWS FETCH NEXT 3 ROWS ONLY 就表示从第 5 行开始往下取 3 行。
中位数 PERCENTILE_CONT()
可以算一组值的中位数,传入一个参数,比如传入0.5 表示 1/2 中位数,0.75 表示 3/4 中位数
SELECT order_type,
percentile_cont(0.5) WITHIN GROUP (
ORDER BY order_qty) AS A,
percentile_cont(0.75) WITHIN GROUP (
ORDER BY order_qty) AS b
FROM wip_order_test
GROUP BY order_type

我们根据订单类型分组后,分别算出每种订单类型数量的 1/2 中位数和 3/4中位数。
1 小时 SQL 极速入门(三)——分析函数的更多相关文章
- 1 小时 SQL 极速入门(一)
前几天,我在论坛溜达.看到一个人发帖说 做了6年的企业级开发,总是被互联网行业的人认为没技术含量,不就是CRUD么 先解释下 CRUD 是什么.CRUD 就是我们常说的增删改查(Create,Retr ...
- 1 小时 SQL 极速入门(二)
上篇我们说了 SQL 的基本语法,掌握了这些基本语法后,我们可以对单表进行查询及计算分析.但是一个大的系统,往往会有数十上百张表,而业务关系又错综复杂.我们要查的数据往往在好几张表中,而要从多张表中来 ...
- Unity3D新手教学,让你十二小时,从入门到掌握!(三 ) [转]
版权声明:本文为Aries原创文章,转载请标明出处.如有不足之处欢迎提出意见或建议,联系QQ531193915 这一讲,我会教大家如何写碰撞检测的代码,然后还会教大家如何使用我介绍给大家的第一个Uni ...
- 《Python黑客编程之极速入门》正式开课
玄魂 玄魂工作室 今天 之前开启了一个<Python黑客编程>的系列,后来中断了,内容当时设置的比较宽,不太适合入门.现在将其拆分成两个系列<Python黑客编程之极速入门>和 ...
- Python 极速入门指南
前言 转载于本人博客. 面向有编程经验者的极速入门指南. 大部分内容简化于 W3School,翻译不一定准确,因此标注了英文. 包括代码一共两万字符左右,预计阅读时间一小时. 目前我的博客长文显示效果 ...
- SQL总结(三)其他查询
SQL总结(三)其他查询 其他常用的SQL,在这里集合. 1.SELECT INTO 从一个表中选取数据,然后把数据插入另一个表中.常用于创建表的备份或者用于对记录进行存档. 语法: SELECT c ...
- SQL 存储过程入门(事务)(四)
SQL 存储过程入门(事务)(四) 本篇我们来讲一下事务处理技术. 为什么要使用事务呢,事务有什么用呢,举个例子. 假设我们现在有个业务,当做成功某件事情的时候要向2张表中插入数据,A表,B表,我 ...
- SQL从入门到基础–03 SQLServer基础1(主键选择、数据插入、数据更新)
一.SQL语句入门 1. SQL语句是和DBMS“交谈”专用的语句,不同DBMS都认SQL语法. 2. SQL语句中字符串用单引号. 3. SQL语句中,对于SQL关键字大小写不敏感,对于字符串值大小 ...
- MyBatis极速入门开发手册(2017-2-6更新)
前言: 本篇文章对我的学习内容做一个归纳梳理,同时也记录一些学习过程中遇上的问题及注意事项等等,可以帮助新入门的朋友们消除一些误区与盲区,希望能帮上一些正在学习的朋友们.在编写时会引用一些mybati ...
随机推荐
- 读书笔记---HTML5实战 MARCO CASARIO(后六章)
画布叠加:用CSS的z-index和position; 第八章 HTML5通信API ①XMLHTTPREQUEST是JS中用于服务器交互的API; ②用HTML5的POSTMESSAGE API实现 ...
- 【bzoj 1095】[ZJOI2007]Hide 捉迷藏
题目链接: TP 题解: 样例好良心,调样例3h一A…… 细节好多……诸如没完没了的pop和push……搞得头都大了. 同情zzh……调了整一天了. 动态点分治裸题……果然每个“裸题”打起来都跟shi ...
- 51nod 1135 原根 就是原根...
%%% dalao Orz ,筛素数到sqrt(n),分解ϕ(p),依次枚举判断就好了 #include<cstdio> #include<cstring> #include& ...
- BZOJ_1212_[HNOI2004]L语言_哈希
BZOJ_1212_[HNOI2004]L语言_哈希 Description 标点符号的出现晚于文字的出现,所以以前的语言都是没有标点的.现在你要处理的就是一段没有标点的文章. 一段文章T是由若干小写 ...
- Python 实现文件复制、删除
Python 实现文件复制.删除 转载至:http://www.cnblogs.com/sld666666/archive/2011/01/05/1926282.html 用python实现了一个小 ...
- Emmagee--APP性能测试工具的基本使用
一.Emmagee介绍 Emmagee是监控指定被测应用在使用过程中占用机器的CPU.内存.流量资源的性能测试小工具.该工具的优势在于如同windows系统性能监视器类似,它提供的是数据采集的功能,而 ...
- github下载和上传项目
git下载和上传项目 下载: git clone +地址 上传: 1.git init 在当前项目的目录中生成本地的git管理(多一个.git文件夹,为隐藏文件) 2.git add .(注意最后面有 ...
- Java8新特性之五:Optional
NullPointerException相信每个JAVA程序员都不陌生,是JAVA应用程序中最常见的异常.之前,Google Guava项目曾提出用Optional类来包装对象从而解决NullPoin ...
- 深入理解Linux内核 学习笔记(4)
第四章 中断和异常 中断通常被分为同步中断和异步中断,同步中断是当指令执行时由CPU控制单元产生的,之所以称为同步,是因为只有在一条指令终止执行后CPU才会发出中断异步中断是由其他硬件设备依照CPU时 ...
- java中如何从一行数据中读取数据
目录 @(如何从一行数据中切割数据) 例如我要从一行学生信息中分割出学号.姓名.年龄.学历等等 ==主要使用split方法,split方法在API中定义如下:== public String[] sp ...