`

Oracle 分析函数

阅读更多

Oracle 分析函数

技术   2009-04-29 11:24   阅读53   评论0  
字号:    
oracle分析函数实际上操作对象是查询出的数据集,也就是说不需二次查询数据库,实际上就是oracle实现了一些我们自身需要编码实现的统计功能,对于简化开发工作量有很大的帮助,特别在开发第三方报表软件时是非常有帮助的。
1.1基本语法
oracle分析函数的语法:
function_name(arg1,arg2,...)
over
(<partition-clause> <order-by-clause ><windowing clause>)
      说明:
1. partition-clause 数据记录集分组
2. order-by-clause   数据记录集排序
3. windowing clause 功能非常强大、比较复杂,定义分析函数在操作行的集合
例一
通过avg分析函数实现查询每个人的工资,以及对应部门的平均工资,

SQL> select ename,sal,deptno,round(avg(sal) over ( partition by deptno order by deptno),2) as avg_sl from emp;

ENAME             SAL     DEPTNO    AVG_SAL
---------- ---------- ---------- ----------
CLARK            2450         10    2916.67
KING             5000         10    2916.67
MILLER           1300         10    2916.67
SMITH             800         20       2175
ADAMS            1100         20       2175
FORD             3000         20       2175
SCOTT            3000         20       2175
JONES            2975         20       2175
ALLEN            1600         30    1566.67
BLAKE            2850         30    1566.67
MARTIN           1250         30    1566.67
JAMES             950         30    1566.67
TURNER           1500         30    1566.67
WARD             1250         30    1566.67

 

1.1.1 partition-clause
数据记录集分组, 就好比group by把列col中相同值分成了一组,上面例子里按deptno分了组。
1.1.2 order-by-clause
a 、要和查询对应的记录集排序一致,否则统计数据交叉比较很理解。
b 、如果查询条件表达式没有排序语句,返回记录集会按照 order-by-clause 排序
1.1.3 windowing-clause
个人理解其为分析函数统计数据范围设定。
a、窗口使用前提:分析函数必须有order-by-clause语句
b、默认窗口范围:RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW  
c、窗口有三种:range、row、specifying
1.1.3.1 range窗口
只对日期和数字类型数据生效,只能按照一个字段排序,在对应的字段数据范围内进行搜索.说明范围和排序的升降有关
a、升序,查找[本行字段数据值-range值,本行数据值]数据集合
b、降序, 查找[本行数据值,本行字段数据值+range值,]数据集合
例二
查询本人工资以及和本人工资差距在100内的员工个数(和自己相同工资的算高于自己)
select ename,sal,greater_num+lower_num  from
(select ename,sal,
count( ename) over ( order by sal desc range 100 preceding)-1 as greater_num ,
((count(ename) over ( order by sal asc range 100 preceding)-1) -
(count(ename) over ( order by sal asc range 0 preceding)-1))
as lower_num from emp) a
order by sal asc;
查询结果:
ENAME
SAL
GREATER_NUM
SMITH
800
0
JAMES
950
0
ADAMS
1100
0
WARD
1250
2
MARTIN
1250
2
MILLER
1300
2
TURNER
1500
1
ALLEN
1600
1
CLARK
2450
0
BLAKE
2850
0
JONES
2975
2
SCOTT
3000
2
FORD
3000
2
KING
5000
0
1.1.3.2 row 窗口
    row 窗口是设定分析函数的数据行数,使用该窗口基本没有限制
           rows n preceding
    即为该窗口数据包括本行前的 n 行以及本行共 (n+1) 行数据
1.1.3.3 specifying 窗口
    实际上统计的函数都是由 specifying 窗口设定, range 、 row 窗口实际是指定了分析的对象(字段、数据行),而具体的行数由 specifying 窗口设定,常用表达式如下:
    unbounded preceding   从当前分区第一行开始,结束于处理的当前行
    current row         从当前行开始 ( 并结束 )
    numberic expression preceding 从当前行的数字表达式之前的行开始
    numberic expression following 从当前行的数字表达式之后的行结束
    在这边可以简化以前的前面的 sql, 查询本人工资以及和本人工资差距在100内的员工个数,sql如下:   

SQL> select ename,sal,count(ename) over (order by sal range between 100 preceding and 100 following)-1 as all_row
  2  from emp;

ENAME             SAL    ALL_ROW
---------- ---------- ----------
SMITH             800          0
JAMES             950          0
ADAMS            1100          0
WARD             1250          2
MARTIN           1250          2
MILLER           1300          2
TURNER           1500          1
ALLEN            1600          1
CLARK            2450          0
BLAKE            2850          0
JONES            2975          2
SCOTT            3000          2
FORD             3000          2
KING             5000          0

 
数据一致。
1.2 常用分析函数
1.   avg(distinct|all expression)   计算组内平均值, distinct 可去除组内重复数据(参见 例一)。
 用distinct的例子:
SQL> select n1,v1,avg(distinct n1) over(partition by v1) as avg_n1
  2  from t2;
运行后可发现结果与例一的结果是不一样(必须找个表里面有重复数据的表才看的出来不同)
2.  count(<distinct><*><expression>) 对组内数据进行计数 (参见 例二)。
3.  cume_dist()   计算一行在组中的相对位置,值的范围( 0 , 1 ]
4.  dense_rank() 根据 order by 子句表达式的值,从查询返回的每一行,计算和其他行的相对位置,序号从 1 开始,有重复值时序号不跳号。
这个函数比较重要,
例三 :
统计每个部门工资前三名的人员信息(重复人员也展现)
select ename,sal,deptno from
(select ename,sal,deptno,dense_rank() over (partitionby deptno orderby sal desc ) as seq_num
from emp) a
where seq_num<=3
查询结果:
ENAME
SAL
deptno
KING
5000
10
CLARK
2450
10
MILLER
1300
10
SCOTT
3000
20
FORD
3000
20
JONES
2975
20
ADAMS
1100
20
BLAKE
2850
30
ALLEN
1600
30
TURNER
1500
30
5. first_value(显示的表达式),last_value(显示的表达式) 返回组内第一个值,最后一个值。
例四 :
查询每个部门工资高和最低的人
一般查询sql
select max(sal),min(sal),deptno from emp groupby deptno
但是无法查询对应人员名称,通过分析函数可以变通实现
    select distinct deptno,
first_value(ename||' : ' ||sal) over ( partitionby deptno orderby sal) asfirst,
first_value(ename||' : ' ||sal) over ( partitionby deptno orderby sal desc) aslast
from emp;
   要说明的last_value()并不类似于max函数,从分析函数语法解析知道,默认窗口下的last_value分析的是当前组的当前的以前数据行以及当前行,因此
   first_value(ename||' : ' ||sal) over ( partitionby deptno orderby sal)
   并不等同于
   last_value(ename||' : ' ||sal) over (partitionby deptno orderby sal desc)
6.  min(expression),max(expression)    返回组内最小,最大值
  select  distinct max(sal) over (partitionby deptno),min(sal) over(partitionby deptno),deptno from emp
 该sql和
select max(sal),min(sal),deptno from emp groupby deptno有点类似
 查看过两者的执行计划,采用分析函数多做了一次排序(在大数据量下没有做测试)。
7.  rank() 和 dense_rank ()函数功能类似,但是有重复值时序号是跳号的。  
比如上dense_rank()查出来是10条记录,但是用rank()查出来是9条记录,其中
ADAMS
1100
20
此条记录是没有的
8. row_number()   返回有序组中的一行的偏移量,也就是对应的序号。
例五 :
    显示每个的信息以及在工作在部门中的(从高到低)排名   

SQL> select ename,sal,deptno,row_number() over (partition by deptno order by sal desc) as sorts
  2  from emp;

ENAME             SAL     DEPTNO      SORTS
---------- ---------- ---------- ----------
KING             5000         10          1
CLARK            2450         10          2
MILLER           1300         10          3
SCOTT            3000         20          1
FORD             3000         20          2
JONES            2975         20          3
ADAMS            1100         20          4
SMITH             800         20          5
BLAKE            2850         30          1
ALLEN            1600         30          2
TURNER           1500         30          3
WARD             1250         30          4
MARTIN           1250         30          5
JAMES             950         30          6

已选择14行。

 分页语句里使用row_number() over:
SQL>select ename,sal from (
       select ename,sal,row_number() over (order by sal desc) as r
    ) where r<=10 and r>=6;
 
9.       sum(expression)   计算组中表达式的累计和
1.3 经典案例
行列转换
将如下表格的数据从行式
ENAME
DEPTNO
SORTNO
KING
10
1
CLARK
10
2
MILLER
10
3
SCOTT
20
1
FORD
20
1
JONES
20
2
ADAMS
20
3
BLAKE
30
1
ALLEN
30
2
TURNER
30
3
改为列式
DEPTNO
HIGHEST
SEC_HIGHEST
THIRD_HIGHEST
10
KING
CLARK
MILLER
20
FORD
JONES
ADAMS
30
BLAKE
ALLEN
TURNER
 
可通过如下在行式 sql 基础上生成, sql 如下:
select deptno, min(decode(seq_num,1,ename,null)) as highest,
min(decode(seq_num,2,ename,null)) as sec_highest,
min(decode(seq_num,3,ename,null)) as third_highest from
(select ename,deptno,seq_num from
(select ename,deptno,dense_rank() over (partitionby deptno orderby sal desc ) as seq_num
from emp) a
where seq_num<=3) b
groupby b.deptno
1.4 说明
1 、在 oracle9i 中 pl/sql 分析器支持分析函数,在程序块中也可以使用(简单测试验证)
2 、使用函数时注意考虑 null 特殊情况,默认值最大,降序排列在最前列。
3 、分析函数使用时需要考虑排序、筛选的复杂度,大批量数据的过于复杂排序、筛选会导致系统资源繁忙。
分享到:
评论

相关推荐

    ORACLE分析函数教程

    ### Oracle分析函数详解 #### 一、Oracle分析函数概述 Oracle分析函数是在处理大量数据时极为有用的一套工具,主要用于在线分析处理(OLAP)场景。这类函数可以在多个级别上进行数据聚合,并支持复杂的排序、分组...

    oracle分析函数文档

    ### Oracle分析函数详解 #### 一、概述 Oracle分析函数是一种强大的工具,它允许用户对分组数据执行复杂的计算,并且结果可以根据特定条件进行动态调整。这种灵活性使得Oracle分析函数在处理复杂的数据集时非常...

    ORACLE分析函数大全

    Oracle分析函数是数据库管理系统Oracle中的一个强大特性,它允许用户在SQL查询中执行复杂的分析操作。分析函数在处理报表和数据迁移任务时尤其有用,因为它们可以基于分组计算聚合值,并为每个分组返回多行,而不...

    oracle分析函数(用法+实例)

    Oracle 分析函数(用法+实例) Oracle 分析函数是 Oracle 8.1.6 版本中引入的高级应用,属于 Oracle 的一大亮点。分析函数可以分为四大类:排名函数、聚合函数、行比较函数和统计函数。下面将对分析函数的原理、...

    ORACLE 分析函数大全

    Oracle 分析函数是一种强大的SQL工具,它允许你在处理数据时执行复杂的分析操作,而不像聚合...参考书籍如Tom Kyte的《Expert One-on-One》和Oracle 9i SQL Reference等,都是深入学习和理解Oracle分析函数的宝贵资源。

    Oracle分析函数

    Oracle 分析函数详解 Oracle 分析函数是 Oracle 数据库中的一种强大功能,能够帮助用户快速进行数据分析和处理。在本文中,我们将对 Oracle 分析函数进行详细的介绍,并对其各个函数进行解释。 一、总体介绍 ...

    oracle 分析函数学习笔记

    Oracle 分析函数是一种高级SQL功能,它允许在单个查询中对数据集进行复杂的分析,无需额外的编程或多次数据库交互。分析函数处理的结果通常基于数据的分组、排序或特定窗口,为统计汇总和复杂的数据分析提供了便利。...

    ORACLE分析函数.pdf

    Oracle分析函数是数据库管理系统Oracle中的一种高级SQL特性,它允许用户在单个查询中对一组行进行计算,而无需使用子查询或自连接。这些函数极大地增强了数据分析和报告的能力,提高了查询性能。以下是对Oracle分析...

    oracle 分析函数

    oracle 分析函数 开发必备 数据库开发工程师

    Oracle分析函数.doc

    Oracle分析函数是数据库管理系统Oracle中的一种高级特性,用于处理和分析数据集,提供了一种高效的方式来执行聚合操作,而无需多次查询数据库。分析函数能够直接在单次查询中完成复杂的数据计算,包括排序、分组、...

    oracle分析函数大全

    ### Oracle分析函数详解 #### 一、概述 Oracle分析函数是一种强大的工具,它自Oracle 8.1.6版本开始引入,并在后续版本中不断完善和发展。这类函数的主要用途在于能够针对一组数据执行复杂的聚合计算,并且不同于...

    Oracle 分析函数.doc

    Oracle 分析函数是数据库查询中的强大工具,它们允许在单个SQL语句中对结果集进行复杂的计算和分组操作,极大地简化了数据分析的过程。在Oracle 8i版本之后引入,分析函数为处理大量数据提供了高效的方法,避免了...

    oracle分析函数

    Oracle分析函数是数据库管理系统Oracle中的一种高级SQL特性,自8.1.6版本引入,极大地扩展了SQL在数据处理和分析上的能力。分析函数的主要作用是进行聚合操作,但与传统的聚合函数(如SUM, COUNT, AVG等)不同,它们...

    ORACLE分析函数.ppt

    ORACLE分析函数 ORACLE分析函数是数据库管理系统中的一种功能强大且灵活的分析工具,能够对数据进行复杂的分析和处理。通过使用分析函数,开发者可以更加方便地实现业务逻辑,提高查询效率和数据处理速度。 在本...

    oracle分析函数参考手册

    ### Oracle分析函数详解 #### 一、概述 Oracle分析函数是一种强大的工具,它允许用户对分组数据执行复杂的计算,并且能够返回多个结果行。这与传统的聚合函数(如`SUM`、`COUNT`等)形成鲜明对比,后者通常只针对...

    oracle分析函数.doc

    Oracle分析函数是数据库管理系统Oracle中一组强大的工具,用于处理集合数据,特别是在复杂的报表和数据分析场景中。它们允许用户在单个SQL查询中执行聚合操作,同时保持行的原始顺序,这是传统的GROUP BY函数无法...

    Oracle分析函数教程

    Oracle分析函数是数据库管理系统Oracle中的一个重要特性,自8.1.6版本开始引入,它们用于执行基于组的聚合计算,并且为每个组返回多行结果,而不仅仅是单行。这使得分析函数在数据分析和报表生成方面非常有用,能够...

Global site tag (gtag.js) - Google Analytics