分析函数是什么?
分析函数是Oracle专门用于解决复杂报表统计需求的功能强大的函数,它可以在数据中进行分组然后计算基于组的某种统计值,并且每一组的每一行都可以返回一个统计值。
分析函数和聚合函数的不同之处是什么?
普通的聚合函数用group by分组,每个分组返回一个统计值,而分析函数采用partition by分组,并且每组每行都可以返回一个统计值。
分析函数的形式
分析函数带有一个开窗函数over(),包含三个分析子句:分组(partition by), 排序(order by), 窗口(rows) ,他们的使用形式如下:over(partition by xxx order by yyy rows between zzz)。
注:窗口子句在这里我只说rows方式的窗口,range方式和滑动窗口也不提
分析函数例子(在scott用户下模拟)
示例目的:显示各部门员工的工资,并附带显示该部分的最高工资。
--显示各部门员工的工资,并附带显示该部分的最高工资。
SELECT E.DEPTNO,
E.EMPNO,
E.ENAME,
E.SAL,
LAST_VALUE(E.SAL)
OVER(PARTITION BY E.DEPTNO
ORDER BY E.SAL ROWS
--unbounded preceding and unbouned following针对当前所有记录的前一条、后一条记录,也就是表中的所有记录
--unbounded:不受控制的,无限的
--preceding:在...之前
--following:在...之后
BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) MAX_SAL
FROM EMP E;
运行结果:
示例目的:按照deptno分组,然后计算每组值的总和
SELECT EMPNO,
ENAME,
DEPTNO,
SAL,
SUM(SAL) OVER(PARTITION BY DEPTNO ORDER BY ENAME) max_sal
FROM SCOTT.EMP;
运行结果:
示例目的:对各部门进行分组,并附带显示第一行至当前行的汇总
SELECT EMPNO,
ENAME,
DEPTNO,
SAL,
--注意ROWS BETWEEN unbounded preceding AND current row 是指第一行至当前行的汇总
SUM(SAL) OVER(PARTITION BY DEPTNO
ORDER BY ENAME
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) max_sal
FROM SCOTT.EMP;
运行结果:
示例目标:当前行至最后一行的汇总
SELECT EMPNO,
ENAME,
DEPTNO,
SAL,
--注意ROWS BETWEEN current row AND unbounded following 指当前行到最后一行的汇总
SUM(SAL) OVER(PARTITION BY DEPTNO
ORDER BY ENAME
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) max_sal
FROM SCOTT.EMP;
运行结果:
示例目标:当前行的上一行(rownum-1)到当前行的汇总
SELECT EMPNO,
ENAME,
DEPTNO,
SAL,
--注意ROWS BETWEEN 1 preceding AND current row 是指当前行的上一行(rownum-1)到当前行的汇总
SUM(SAL) OVER(PARTITION BY DEPTNO
ORDER BY ENAME ROWS
BETWEEN 1 PRECEDING AND CURRENT ROW) max_sal
FROM SCOTT.EMP;
运行结果:
示例目标: 当前行的上一行(rownum-1)到当前行的下辆行(rownum+2)的汇总
SELECT EMPNO,
ENAME,
DEPTNO,
SAL,
--注意ROWS BETWEEN 1 preceding AND 1 following 是指当前行的上一行(rownum-1)到当前行的下辆行(rownum+2)的汇总
SUM(SAL) OVER(PARTITION BY DEPTNO
ORDER BY ENAME
ROWS BETWEEN 1 PRECEDING AND 2 FOLLOWING) max_sal
FROM SCOTT.EMP;
运行结果:
评级函数
常见评级函数如下:
- RANK():返回数据项在分组中的排名,在排名相等时会在名次中留下空位,造成排名不连续。
- DENSE_RANK():同样返回数据项在分组中排名,不过在排名相等时不会留下名位空位。
- CUME_DIST():返回特定值相对于一组值的位置,是累积分布(cumulative distribution)的简写。
- PERCENT_RANK():返回某个值相对于一组值的百分比排名。
- NTILE():返回n分片后的值,如三分片、四分片等。
- ROW_NUMBER():为每一条分组记录返回一个数字,注意不同于rownum伪列。
RANK()和DENSE_RANK()
rank()和dense_rank()函数都可用于计算数据项在分组中(在不使用partition by时以所有数据为一个分组)的排名。它们的区别在于rank()在排名相等时,如:有3个第1名时,则下一个排名为第4名,没有2、3名;而dense_rank()则在有3个第1名时,下一个排名为第2名。即,rank()会出现排名间隔,而dense_rank()则不会出现排名间隔。
这两个函数多用于select子句中,在不进行分组的情况下,可以不使用partition by子句。其使用举例如,找出公司所有人工资排名:
select ename,
rank() over (order by sal desc) rank,
dense_rank() over (order by sal desc) dense_rank
from emp;
从语句中可以看出,rank()函数需要有关键字over和order by。而且rank()是一个单值函数,而不是聚合函数。若需要找出每种工作的最高工资在所有工作最高工资中的排名:
select job,
rank() over (order by max(sal) desc) rank,
dense_rank() over (order by max(sal) desc) dense_rank
from emp
group by job;
在排名中,会出现NULL值在前在后的问题,可以在ORDER BY子句之后使用关键字NULLS FIRST/LAST来控制。
PARTITION BY子句
当需要进行获得分组后各组内的排名,则需要使用partition by子句。它不同于group by的分组,这种分组不“合并聚合”,它相当于把值分组后计算,然后重复每个值。
最常见的例子如:在table表中有name(姓名)、class(班级)和score(分数)三个字段,求每个班级里前三名姓名、班级及分数,SQL语句为:
select name,class,score
from (select name,
class,
score,
rank() over(partition by class order by score desc) rank
from table)
where rank <= 3;
在SCOTT用户中测试,求每个部门工资前3名的人姓名、部门、工作和工资,如:
select *
from (select ename,
deptno,
job,
sal,
dense_rank() over(partition by deptno order by sal desc) rank
from emp)
where rank <= 3;
ROW_NUMBER()
row_number为每一行返回一个数字,在分组中较常用(rownum在非分组中常用)。如,给emp表中每种工作工资由高到低进行排序:
select ename,job,sal,row_number() over (partition by job order by sal desc) from emp;
窗口函数(累计和、移动平均值等)
窗口函数可用来计算累计和、移动平均值和中心平均值等,具体如下:
计算累计和
查询从2003年1月到12月的累计销量,SQL语句如下:
SELECT month,
SUM(amount) AS month_amount,
SUM(SUM(amount)) OVER (ORDER BY month ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS cumulative_amount
FROM all_sales
where year = 2003
GROUP BY month
ORDER BY month;
对于累计部分SUM(SUM(amount)) OVER (ORDER BY month ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)解析如下:
- SUM(SUM(amount))中内部的SUM(amount)用于计算月销量总和,外部的SUM()用于计算累计销量。
- ORDER BY month 按月份对查询读取的记录进行排序。
- ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW定义了窗口的起点和终点,起点为UNBOUNDED PRECEDING,意味着起点为固定的查询结果集的第一行;终点为CURRENT ROW表示终点为处理结果集的当前行。当外部SUM函数计算返回当前的累计销量后,窗口的终点便向下移动一行。PRECEDING表示向上累计数,若将UNBOUNDED换成数字如1,则表示跟之前一条记录做累积;同时还可以向后,使用关键字FOLLOWING,指定向后累积数只需要在该关键字前加数字即可,该数字为向后累积的行数(从这里也可以看出排序的重要性)。
如:
若要计算指定月份如6月到12月的累积销量,则只需要在where子句中再增加条件month between 6 and 12即可。
计算当月跟前3个月累积销量,窗口语句:
SUM(SUM(amount)) OVER (ORDER BY month ROWS BETWEEN 3 PRECEDING AND CURRENT ROW) AS cumulative_amount
计算前一个月和后一个月累积销量,窗口语句:
SUM(SUM(amount)) OVER (ORDER BY month ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS cumulative_amount
计算移动平均值
计算本月与前3个月之间销量的移动平均值,SQL语句如下:
SELECT month,
SUM(amount) AS month_amount,
AVG(SUM(amount)) OVER (ORDER BY month ROWS BETWEEN 3 PRECEDING AND CURRENT ROW) AS moving_average
FROM all_sales
where year = 2003
GROUP BY month
ORDER BY month;
对移动平均值部分AVG(SUM(amount)) OVER (ORDER BY month ROWS BETWEEN 3 PRECEDING AND CURRENT ROW)解析如下:
- AVG(SUM(amount))内部的sum(amount)计算月销量和,外部的avg()计算平均值。
- ORDER BY month 按月份对查询读取的记录进行排序(这是必须的,因为只有排序后才能做累积或前后求平均值)。
- ROWS BETWEEN 3 PRECEDING AND CURRENT ROW定义了窗口的起点为当前记录的前3条记录,窗口的终点为当前记录。
计算中心平均值
计算当前月份前、后各一个月的销量移动平均值,SQL语句如下:
SELECT month,
SUM(amount) AS month_amount,
AVG(SUM(amount)) OVER (ORDER BY month ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS moving_average
FROM all_sales
where year = 2003
GROUP BY month
ORDER BY month;
对中心平均值部分AVG(SUM(amount)) OVER (ORDER BY month ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING)解析如下:
- AVG(SUM(amount))内部的sum(amount)计算月销量和,外部的avg()计算平均值。
- ORDER BY month 按月份对查询读取的记录进行排序(这是必须的,因为只有排序后才能做累积或前后求平均值)。
- ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING定义了窗口的起点是当前记录之前的那条记录,窗口的终点是当前记录之后的那条记录。
窗口第一条和最后一条记录
FIRST_VALUE()和LAST_VALUE()函数可用于获取窗口中的第一行和最后一行数据,如,可用于获取当前月前一个月和后一个月的销量:
SELECT month,
SUM(amount) AS month_amount,
FIRST_VALUE(SUM(amount)) OVER (ORDER BY month ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS pre_month_amount,
LAST_VALUE(SUM(amount)) OVER (ORDER BY month ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS next_month_amount
FROM all_sales
where year = 2003
GROUP BY month
ORDER BY month;
其中,窗口定义了起点为前一个月终点为后一个月,故而first_value(sum(amount))为前一个月销量而last_value()为后一个月销量。
小学生之Oracle分析函数的更多相关文章
-
Oracle分析函数入门
一.Oracle分析函数入门 分析函数是什么?分析函数是Oracle专门用于解决复杂报表统计需求的功能强大的函数,它可以在数据中进行分组然后计算基于组的某种统计值,并且每一组的每一行都可以返回一个统计 ...
-
[转]oracle分析函数Rank, Dense_rank, row_number
oracle分析函数Rank, Dense_rank, row_number 分析函数2(Rank, Dense_rank, row_number) 目录 ==================== ...
-
[转]oracle 分析函数over
oracle 分析函数over 分析函数(OVER) 目录: =============================================== 1.Oracle分析函数简介 2. O ...
-
oracle分析函数与over()(转)
文章参考:http://blog.csdn.net/haiross/article/details/15336313 -- Oracle分析函数入门-- 分析函数是什么? 分析函数是Oracle专门用 ...
-
Oracle分析函数 — rank, dense_rank, row_number用法
本文通过例子演示了Oracle分析函数 —— rank, dense_rank, row_number的用法. //首先建score表 create table score( course nva ...
-
常用Oracle分析函数详解 [http://www.cnblogs.com/benio/archive/2011/06/01/2066106.html]
学习步骤:1. 拥有Oracle EBS demo 环境 或者 PROD 环境2. copy以下代码进 PL/SQL3. 配合解释分析结果4. 如果网页有点乱请复制到TXT中查看 /*假设一个经理 ...
-
oracle分析函数技术详解(配上开窗函数over())
一.Oracle分析函数入门 分析函数是什么?分析函数是Oracle专门用于解决复杂报表统计需求的功能强大的函数,它可以在数据中进行分组然后计算基于组的某种统计值,并且每一组的每一行都可以返回一个统计 ...
-
Oracle分析函数——函数列表
--------------聚合函数 SUM :该函数计算组中表达式的累积和 MIN :在一个组中的数据窗口中查找表达式的最小值 MAX :在一个组中的数据窗口中查找表达式的最大值 AVG :用于计算 ...
-
强大的oracle分析函数
转载:https://www.cnblogs.com/benio/archive/2011/06/01/2066106.html 学习步骤:1. 拥有Oracle EBS demo 环境 或者 PRO ...
随机推荐
-
获取PHP文件绝对地址$_SERVER[&#39;SCRIPT_FILENAME&#39;] 与 __FILE__ 的区别
通常情况下,PHP $_SERVER['SCRIPT_FILENAME'] 与 __FILE__ 都会返回 PHP 文件的完整路径(绝对路径)与文件名: <?php echo 'SCRIPT_F ...
-
C#中(int)、int.Parse()、int.TryParse()和Convert.ToInt32()的区别 <;转>;
作者:Statmoon 出处:http://leolis.cnblogs.com/ 在编程过程中,数据转换是经常要用到的,C#中数据转换的方法很多,拿将目标对象转换为整型(int)来讲,有四种方法 ...
-
JS Json数据转换
*** json字符串中不能出现单引号,不然JSON.parse会报错,处理方式将单引号转义 概述 JSON.stringify() 方法可以将任意的 JavaScript 值序列化成 JSON 字符 ...
-
.NET web开发之WebApi初试水
前几天看了.NET的EF(Entity Framework),发现居然有这么先进的东西,只要操作几个类就可以完成数据库的增删查改,而且可以用数据库直接导出类(DB First).也可以用类来生成数据库 ...
-
html 关于块级元素和行内元素
常用的行内元素要记住:a.span.img.input.lable.select.strong.textarea 常用的块级元素要记住:div.h1~h6.dl.ul.ol 例如在一个title中,有 ...
-
python list(列表)和tuple(元组)
200 ? "200px" : this.width)!important;} --> 介绍 python中存在两种有序的类型列表,分别是list(列表)和tuple(元组) ...
-
[ lucene高级 ] 研讨如何进行Lucene的分布式应用
http://www.cnblogs.com/huangfox/archive/2010/10/15/1852206.html Lucene是个高度优化的倒转索引搜索引擎.它将倒转的索引存储在定制的文 ...
-
CSS3详解:transform、transition
CSS3 transform是什么? transform的含义是:改变,使-变形:转换 CSS3 transform都有哪些常用属性? transform的属性包括:rotate() / skew() ...
-
Django的自定义标签
Django提供了自定义标签功能,可以方便常用方法的重复使用. 标签的本质就是函数,标签名就是函数名. 注意点: 1.需要到django.template对象. 2.register = templa ...
-
Hyper-V在线调整虚拟硬盘大小
从Windows Server 2012 R2 开始,可以在线调整虚拟硬盘的大小了,这意味着当虚拟硬盘不够用时,我们在虚拟机运行的情况下直接扩展虚拟硬盘容量了.有人说这个有什么用?当然,实验室情况下, ...