Oracle从8.1.6开始提供分析函数,分析函数用于计算基于组的某种聚合值,它和聚合函数的不同之处是对于每个组返回多行,而聚合函数对于每个组只返回一行。
语法:

Sql代码

  1. <analytic-function>(<argument>,<argument>,...)   
  2. over(   
  3. <query-partition-clause>   
  4. <order-by-clause>   
  5. <windowing-clause>   
  6. )  
说明: 
<1> over是关键字,用于标识分析函数。
<2> <analytic-function>是指定的分析函数的名字。
<3> <argument>为参数,分析函数可以选取0-3个参数。
<4> 分区子句<query-partition-clause>的格式为:
     partition by<value_exp>[,value_expr]...
    关键字partition by子句根据由分区表达式的条件逻辑地将单个结果集分成N组。这里的"分区partition"和"组group" 都是同义词。
<5> 排序子句order-by-clause指定数据是如何存在分区内的。其格式为:
order[siblings]by{expr|position|c_alias}[asc|desc][nulls first|nulls last]
其中:
     A.asc|desc:指定了排列顺序。
     B.nulls first|nulls last:指定了包含空值的返回行应出现在有序序列中的第一个或最后一个位置。
<6>窗口子句windowing-clause
    给出一个固定的或变化的数据窗口方法,分析函数将对这些数据进行操作。在一组基于任意变化或固定的窗口中,
可用该子句让分析函数计算出它的值。
格式:
{rows|range}
{between
{unbounded preceding|current row |<value_expr>{preceding|following}
}and
{unbounded preceding|current row |<value_expr>{preceding|following}
}|{unbounded preceding|current row |<value_expr>{preceding|following
}}
    A.rows|range:此关键字定义了一个window。
     B.between...and...:为窗品指一个起点和终点。
     C.unbounded preceding:指明窗口是从分区(partition)的第一行开始。
     D.current row:指明窗口是从当前行开始。 开窗函数:
       开窗函数指定了分析函数工作的数据窗口大小,这个数据窗口大小可能会随着行的变化而变化,举例如下:

  • over(order by salary) 按照salary排序进行累计,order by是个默认的开窗函数
  • over(partition by deptno)按照部门分区
  • over(order by salary range between 50 preceding and 150 following) 每行对应的数据窗口是之前行幅度值不超过50,之后行幅度值不超过150
  • over(order by salary rows between 50 preceding and 150 following) 每行对应的数据窗口是之前50行,之后150行
  • over(order by salary rows between unbounded preceding and unbounded following)每行对应的数据窗口是从第一行到最后一行,等效: over(order by salary range between unbounded preceding and unbounded following)

1、Oracle ROLLUP和CUBE 用法

      Oracle的GROUP BY语句除了最基本的语法外,还支持ROLLUP和CUBE语句。如果是Group by  ROLLUP(A, B, C)的话,首先会对(A、B、C)进行GROUP BY,然后对(A、B)进行GROUP BY,然后是(A)进行GROUP BY,最后对全表进行GROUP BY操作。

      如果是GROUP BY CUBE(A, B, C),则首先会对(A、B、C)进行GROUP BY,然后依次是(A、B),(A、C),(A),(B、C),(B),(C),最后对全表进行GROUP BY操作。也可以 Group by Rollup(A,(B,C)) ,Group by A Rollup(B,C),……

      如何来区分到底是根据那个字段做的汇总呢,这时候,oracle的grouping函数就粉墨登场了.如果当前的汇总记录是利用该字段得出的,grouping函数就会返回1,否则返回0。

示例:

Sql代码

  1. select nvl(area_code,'合计') area_code,sum(local_fare) local_fare  
  2. from t  
  3. group by rollup(nvl(area_code,'合计')); 

Sql代码

  1. select area_code,bill_month,sum(local_fare) local_fare  
  2. from t  
  3. group by cube(area_code,bill_month)  
  4. order by area_code,bill_month nulls last; 

Sql代码

  1. select decode(grouping(area_code),1,'all area',to_char(area_code)) area_code,  
  2. decode(grouping(bill_month),1,'all month',bill_month) bill_month,  
  3. sum(local_fare) local_fare  
  4. from t  
  5. group by cube(area_code,bill_month)  
  6. order by area_code,bill_month nulls last; 

    简单点说:为了生成数据统计以及横向小计统计,可以在GROUP BY子句中使用ROLLUP操作符。为了生成数据统计、横向小计、纵向小计结果,可以使用CUBE操作符。

2、Rank的用法

       功能描述:根据ORDER BY子句中表达式的值,从查询返回的每一行,计算它们与其它行的相对位置。组内的数据按ORDER BY子句排序,然后给每一行赋一个号,从而形成一个序列,该序列从1开始,往后累加。每次ORDER BY表达式的值发生变化时,该序列也随之增加。有同样值的行得到同样的数字序号(认为null时相等的)。然而,如果两行的确得到同样的排序,则序数将随后跳跃。若两行序数为1,则没有序数2,序列将给组中的下一行分配值3,DENSE_RANK则没有任何跳跃。

       rank()是跳跃排序,比如有两个第二名时接下来就是第四名(同样是在各个分组内)

       dense_rank()是连续排序,比如有两个第二名时仍然跟着第三名。

示例:

Sql代码

  1. select area_code,sum(local_fare) local_fare,  
  2. rank() over (order by sum(local_fare) desc) fare_rank  
  3. from t  
  4. group by area_code; 

结果:

AREA_CODE LOCAL_FARE FARE_RANK

---------- -------------- ----------

5765      104548.72   1

5761      54225.41    2

5763      54225.41    2

5764      53156.77    4

5762      52039.62    5

Sql代码

  1. select area_code,sum(local_fare) local_fare,  
  2. dense_rank() over (order by sum(local_fare) desc ) fare_rank  
  3. from t  
  4. group by area_code; 

结果:

AREA_CODE LOCAL_FARE FARE_RANK

---------- -------------- ----------

5765      104548.72   1

5761      54225.41    2

5763      54225.41    2

5764      53156.77    3 这是这里出现了第三名

5762      52039.62    4

ROW_NUMBER

功能描述:返回有序组中一行的偏移量,从而可用于按特定标准排序的行号。

Sql代码

  1. select area_code,sum(local_fare) local_fare,  
  2. row_number() over (order by sum(local_fare) desc ) fare_rank  
  3. from t  
  4. group by area_code; 

结果:

AREA_CODE LOCAL_FARE FARE_RANK

---------- -------------- ----------

5765     104548.72    1

5761     54225.41     2

5763     54225.41     3

5764     53156.77     4

rank()示例:

a. 取出数据库中最后入网的n个用户

Sql代码

  1. select user_id,tele_num,user_name,user_status,create_date   
  2. from (  
  3. select user_id,tele_num,user_name,user_status,create_date,  
  4. rank() over (order by create_date desc) add_rank  
  5. from user_info  
  6. )  
  7. where add_rank <= :n; 

b.根据object_name删除数据库中的重复记录

create table t as select obj#,name from sys.obj$;

再insert into t1 select * from t1 数次.

Sql代码

  1. delete from t1 where rowid in (  
  2. select row_id from (  
  3. select rowid row_id,row_number() over (partition by obj# order by rowid ) rn  
  4. ) where rn <> 1  
  5. ); 

c. 取出各地区的话费收入在各个月份排名.

Sql代码

  1. select bill_month,area_code,sum(local_fare) local_fare,  
  2. rank() over (partition by bill_month order by sum(local_fare) desc) area_rank  
  3. from t  
  4. group by bill_month,area_code 

结果:

BILL_MONTH AREA_CODE LOCAL_FARE AREA_RANK

--------------- --------------- -------------- ----------

200405        5765    25057.74      1

200405        5761    13060.43      2

200405        5763    13060.43      2

200405        5762    12643.79      4

200405        5764    12487.79      5

200406        5765    26058.46      1

200406        5761    13318.93      2

200406        5763    13318.93      2

200406        5764    13295.19      4

200406        5762    12795.06      5

200407        5765    26301.88      1

200407        5761    13710.27      2

200407        5763    13710.27      2

200407        5764    13444.09      4

200407        5762    13224.30      5

3、First/Last的用法

    First功能描述:从DENSE_RANK返回的集合中取出排在最前面的一个值的行(可能多行,因为值可能相等),因此完整的语法需要在开始处加上一个集合函数以从中取出记录。

     Last功能描述:从DENSE_RANK返回的集合中取出排在最后面的一个值的行(可能多行,因为值可能相等),因此完整的语法需要在开始处加上一个集合函数以从中取出记录。

示例:下面例子中DENSE_RANK按部门分区,再按佣金commission_pct排序,FIRST取出佣金最低的对应的所有行,然后前面的MIN函数从这个集合中取出薪水最低的值;LAST取出佣金最高的对应的所有行,然后前面的MAX函数从这个集合中取出薪水最高的值。

Sql代码

  1. SELECT last_name, department_id, salary,  
  2. MIN(salary) KEEP (DENSE_RANK FIRST ORDER BY commission_pct)  
  3. OVER (PARTITION BY department_id) "Worst",  
  4. MAX(salary) KEEP (DENSE_RANK LAST ORDER BY commission_pct)  
  5. OVER (PARTITION BY department_id) "Best"
  6. FROM employees  
  7. WHERE department_id in (20,80)  
  8. ORDER BY department_id, salary; 

结果:

LAST_NAME DEPARTMENT_ID SALARY Worst Best

------------------------- ------------- ---------- ---------- ----------

Fay 20 6000 6000 13000

Hartstein 20 13000 6000 13000

Kumar 80 6100 6100 14000

Banda 80 6200 6100 14000

Johnson 80 6200 6100 14000

4、FIRST_VALUE/LAST_VALUE的用法

      FIRST_VALUE、LAST_VALUE是两个分析函数。返回结果集中排在第一位和最后一位的值。语法是:

FIRST_VALUE (expr) OVER ( analytic_clause)

示例:

计算按部门分区按薪水排序的数据窗口的第一个值对应的名字,如果薪水的第一个值有多个,则从多个对应的名字中取缺省排序的第一个名字。

Sql代码

  1. SELECT department_id, last_name, salary, FIRST_VALUE(last_name)  
  2. OVER (PARTITION BY department_id ORDER BY salary ASC ) AS lowest_sal  
  3. FROM employees  
  4. WHERE department_id in(20,30); 

结果:

DEPARTMENT_ID LAST_NAME SALARY LOWEST_SAL

------------- ------------------------- ---------- --------------

20 Fay 6000 Fay

20 Hartstein 13000 Fay

30 Colmenares 2500 Colmenares

30 Himuro 2600 Colmenares

30 Tobias 2800 Colmenares

30 Baida 2900 Colmenares

30 Khoo 3100 Colmenares

30 Raphaely 11000 Colmenares

5、Lag/Lead的用法

       功能描述:可以访问结果集中的其它行而不用进行自连接。它允许去处理游标,就好像游标是一个数组一样。在给定组中可参考当前行之前的行,这样就可以从组中与当前行一起选择以前的行。Offset是一个正整数,其默认值为1,若索引超出窗口的范围,就返回默认值(默认返回的是组中第一行),其相反的函数是LEAD。

示例:lag和lead函数介绍取出每个月的上个月和下个月的话费总额

Sql代码

  1. select area_code,bill_month, local_fare cur_local_fare,  
  2. lag(local_fare,2,0) over (partition by area_code order by bill_month ) pre_local_fare,  
  3. lag(local_fare,1,0) over (partition by area_code order by bill_month ) last_local_fare,  
  4. lead(local_fare,1,0) over (partition by area_code order by bill_month ) next_local_fare,  
  5. lead(local_fare,2,0) over (partition by area_code order by bill_month ) post_local_fare  
  6. from (  
  7. select area_code,bill_month,sum(local_fare) local_fare  
  8. from t  
  9. group by area_code,bill_month  

结果:

AREA_CODE BILL_MONTH CUR_LOCAL_FARE PRE_LOCAL_FARE LAST_LOCAL_FARE NEXT_LOCAL_FARE POST_LOCAL_FARE

--------- ---------- -------------- -------------- --------------- --------------- ---------------

5761 200405 13060.433 0 0 13318.93 13710.265

5761 200406 13318.93 0 13060.433 13710.265 14135.781

5761 200407 13710.265 13060.433 13318.93 14135.781 0

5761 200408 14135.781 13318.93 13710.265 0 0

5762 200405 12643.791 0 0 12795.06 13224.297

5762 200406 12795.06 0 12643.791 13224.297 13376.468

5762 200407 13224.297 12643.791 12795.06 13376.468 0

5762 200408 13376.468 12795.06 13224.297 0 0

6.RATIO_TO_REPORT用法

功能描述:该函数计算expression/(sum(expression))的值,它给出相对于总数的百分比,即当前行对sum(expression)的贡献。

格式:RATIO_TO_REPORT (expr) OVER (query_partition_clause)

示例:计算每个员工的工资占该类员工总工资的百分比

Sql代码

  1. SELECT last_name, salary, RATIO_TO_REPORT(salary) OVER () AS rr  
  2. FROM employees  
  3. WHERE job_id = 'PU_CLERK'; 

7.GROUPING SETS用法

     从Oracle9i开始,使用GROUPING SETS操作符可以合并多个分组的结果。并且可以用GROUP BY GROUPING SETS来代替GROUP BY CUBE。你可以应用来指定你感兴趣的总数组合。因为它不必计算它不需要集合(也不会产生太多结果),所以对SQL引擎来说更为高效。

其格式为:

GROUP BY GROUPING SETS ((list), (list) ... )

      这里(list)是圆括号中的一个列序列,这个组合生成一个总数。要增加一个总和,必须增加一个(NUlL)分组集。

示例:如果只要生成每项产品(包括所有顾客和通道)和每个顾客/通道组合(包括所有产品)的总数。

Sql代码

  1. SELECT prod_id, cust_id, channel_id, SUM(quantity_sold)  
  2. FROM sales  
  3. WHERE cust_id < 3  
  4. GROUP BY GROUPING SETS (  
  5. (prod_id), (cust_id, channel_id) ,NULL
  6. ); 

示例:统计人员的获奖数

Sql代码

  1. SELECT
  2.       (CASE WHEN grouping(a.c_xm)=1 AND grouping(a.n_jxdm)=1 AND grouping(a.c_rydm)=1  
  3. THEN '合计'
  4. WHEN grouping(a.n_jxdm)=1 AND grouping(a.c_rydm)=1  
  5. THEN '小计'
  6. ELSE a.c_xm  
  7. END) c_xm  
  8.       ,a.n_jxdm,a.c_rydm,COUNT(*)  
  9. FROM T_SK_JPGL_HJMD a  
  10. GROUP BY grouping sets (a.c_xm,(a.c_xm,a.n_jxdm,a.c_rydm),NULL) 

摘录自:http://log-cd.javaeye.com/blog/405187

oracle 统计/分析函数的更多相关文章

  1. oracle 统计分析函数

    http://www.cnblogs.com/advocate/archive/2010/11/16/1878693.html

  2. oracle的分析函数over 及开窗函数

    转:http://www.2cto.com/database/201310/249722.html oracle的分析函数over 及开窗函数   一:分析函数over   Oracle从8.1.6开 ...

  3. Oracle 10gR2分析函数

    Oracle 10gR2分析函数汇总 (Translated By caizhuoyi 2008‐9‐19) 说明:  1. 原文中底色为黄的部分翻译存在商榷之处,请大家踊跃提意见:  2. 原文中淡 ...

  4. Oracle所有分析函数<转>

    Oracle分析函数——函数列表 SUM        :该函数计算组中表达式的累积和 MIN        :在一个组中的数据窗口中查找表达式的最小值 MAX        :在一个组中的数据窗口中 ...

  5. 超级牛皮的oracle的分析函数over(Partition by...) 及开窗函数 (转)

    http://zonghl8006.blog.163.com/blog/static/4528311520083995931317/ over(Partition by...) 一个超级牛皮的ORAC ...

  6. 超级牛皮的oracle的分析函数over(Partition by...) 及开窗函数

    over(Partition by...) 一个超级牛皮的ORACLE特有函数. 天天都用ORACLE,用了快2年了.最近才接触到这个功能强大而灵活的函数.真实惭愧啊! oracle的分析函数over ...

  7. oracle的分析函数over(Partition by...) 及开窗函数

        over(Partition by...) 一个超级牛皮的ORACLE特有函数. oracle的分析函数over 及开窗函数一:分析函数overOracle从8.1.6开始提供分析函数,分析函 ...

  8. oracle 之分析函数 over (partition by ...order by ...)

    一:分析函数overOracle从8.1.6开始提供分析函数,分析函数用于计算基于组的某种聚合值,它和聚合函数的不同之处是对于每个组返回多行,而聚合函数对于每个组只返回一行. 1.分析函数和聚合函数的 ...

  9. 有关Oracle统计信息的知识点[z]

    https://www.cnblogs.com/sunmengbbm/p/5775211.html 一.什么是统计信息 统计信息主要是描述数据库中表,索引的大小,规模,数据分布状况等的一类信息.例如, ...

随机推荐

  1. Python之协程函数

    Python之协程函数 什么是协程函数:如果一个函数内部yield的使用方法是表达式形式的话,如x=yield,那么该函数成为协程函数. def eater(name): print('%s star ...

  2. stark组件之添加、修改页面内容搭建(七)

    如何快速的进行数据的添加以及修改呢?modelform来实现是可以达到效果的,在这里就是应用了modelform,每一个表都不同,所以需要创建不同的modelform. def get_model_f ...

  3. pandas的合并、连接、去重、替换

    import pandas as pd import numpy as np # merge合并 ,类似于Excel中的vlookup df1 = pd.DataFrame({'key': ['K0' ...

  4. 一个关于vue+mysql+express的全栈项目(一)

    最近学了mysql数据库,寻思着能不能构思一个小的全栈项目,思来想去,于是就有了下面的项目: 先上几张效果图吧       目前暂时前端只有这几个页面,后端开发方面,有登录,注册,完善用户信息,获取用 ...

  5. uva 1592 Database (STL)

    题意: 给出n行m列共n*m个字符串,问有没有在不同行r1,r2,有不同列c1,c2相同.即(r1,c1) = (r2,c1);(r1,c2) = (r2,c2); 如 2 3 123,456,789 ...

  6. Java线程和多线程(一)——线程的基本概念

    Java 线程是一个轻量级执行任务的处理单元.Java提供了Thread类来支持多线程,开发者在应用中可以创建多个线程来支持并发执行任务. 在应用中存在两种类型的线程,用户线程和守护线程.当我们启动应 ...

  7. [POJ3463] Sightseeing(次短路 Heap + Dijkstra)

    传送门 用dijkstra比较好,spfa可能有的重复 dis[x][2]:dis[x][0]表示起点到x的最短路.dis[x][1]表示起点到x的次短路: tot[x][2]:tot[x][0]表示 ...

  8. 将windows应用程序注册为windows服务

    @echo off::设置服务名称set service_name=ServiceManagement ::设置服务描述set service_description=文件安全上传服务 ::设置服务程 ...

  9. Chains (链 )

    Indy 中的工作队列系统,调度器,和链引擎都被叫做链. 当使用链的时候,一个基于链的 IOHandler 存储工作项目到有关的工作队列中.在一个工作单元被完成以前,执行这个工作单元的纤程是无法做其它 ...

  10. Ubuntu如何开启root账户登录

    1 首先设置root密码,利用现有管理员帐户登陆Ubuntu,在终端执行命令:sudo passwd root,接着输入密码和root密码,重复密码.这样就有了可用的root用户.   2 打开一个终 ...