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 ...
随机推荐
- 详解Linux文档属性、拥有者、群组、权限、差异
写在前面 我们都知道Linux是一个支持多用户.多任务的系统,这也是它最优秀的特性,即可能同时有很多人都在系统上进行工作,所以千万不要强制关机,同时,为了保护每个人的隐私和工作环境,针对某一个文档(文 ...
- Spark2.1.0——运行环境准备
学习一个工具的最好途径,就是使用它.这就好比<极品飞车>玩得好的同学,未必真的会开车,要学习车的驾驶技能,就必须用手触摸方向盘.用脚感受刹车与油门的力道.在IT领域,在深入了解一个系统的原 ...
- 基于Jmeter+maven+Jenkins构建性能自动化测试平台
一.目的: 为能够将相关系统性能测试做为常规化测试任务执行,且可自动无人值守定时执行并输出性能测试结果报告及统计数据,因此基于Jmeter+maven+Jenkins构建了一套性能自动化测试平台 ...
- Vector简单介绍
/*枚举就是Vector特有的取出方式发现枚举和迭代器很像其实枚举和迭代是一样的因为枚举的名称以及方法的名称都过长了.所以被迭代器取代了枚举郁郁而终了. */ import java.util.*;c ...
- remove方法
1.jQuery的remove()方法 http://www.365mini.com/page/jquery-remove.htm ①返回值是jquery对象本身 所以可以做删除再添加的操作 // 移 ...
- 把封装脚本做成jar包
前提: eclipse, selenium, maven 把二次封装过的脚本做成jar包, 这样可以在新建工程里也调用封装过的方法. 实现步骤: 1. project 右键 => maven = ...
- 请注意写代码的习惯与态度(Java)
注: 以下内容引自http://blog.csdn.net/xtayfjpk/article/details/52136686 请注意写代码的习惯与态度(Java) 原创 2016年08月06日 16 ...
- [USACO11JAN]大陆议会The Continental Cowngress_2-sat
[USACO11JAN]大陆议会The Continental Cowngress_2-sat 题意: 由于对Farmer John的领导感到极其不悦,奶牛们退出了农场,组建了奶牛议会. 议会以“每头 ...
- laravel 查询数据返回的结果
laravel查询数据返回的结果 在插入数据库的时候,发现查询数据返回的结果是一个对象;即使是空数据 返回的不是true或者false 那么要判断该结果是否查询有结果 该如果呢? 学习源头: http ...
- FileInputStream与BufferedInputStream的对比
FileInputStream inputStream = new FileInputStream("d://vv.mp4"); FileOutputStream outputSt ...