oracle 统计/分析函数

--oracle 统计/分析函数
/*
Sql代码
<analytic-function>(<argument>,<argument>,...)    
over(    
<query-partition-clause>    
<order-by-clause>    
<windowing-clause>    
)   
说明: 
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)每行对应的数据窗口是从第一行到最后一行
*/

/*
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),…… 
*/

Select nvl(to_char(deptno), 'all_dept'), Sum(sal)
  From emp
 Group By Rollup(deptno);

/*
10	      9341
20	      11023
30	      31110
all_dept	51474
*/

Select nvl(to_char(deptno), 'all_dept'),
       nvl(to_char(job), 'all_job'),
       Sum(sal)
  From emp
 Group By Rollup(deptno, job);

/*
10	      CLERK	      3341
10	      MANAGER	    2000
10	      PRESIDENT	  4000
10	      all_job	    9341
20	      CLERK	      6000
20	      ANALYST	    3123
20	      MANAGER	    1900
20	      all_job	    11023
30	      CLERK	      7000
30	      MANAGER	    1000
30	      SALESMAN	  23110
30	      all_job	    31110
all_dept	all_job	    51474
*/
 
Select decode(Grouping(deptno), 1, '_dept', to_char(deptno)) deptno,
       decode(Grouping(job), 1, '_job', to_char(job)) job,
       Sum(sal)
  From emp
 Group By cube(deptno, job)
 order by deptno,job;
 
/*
10	  CLERK	    3341
10	  MANAGER	  2000
10	  PRESIDENT	4000
10	  _job	    9341
20	  ANALYST	  3123
20	  CLERK	    6000
20	  MANAGER	  1900
20	  _job	    11023
30	  CLERK	    7000
30	  MANAGER	  1000
30	  SALESMAN	23110
30	  _job	    31110
_dept	ANALYST	  3123
_dept	CLERK	    16341
_dept	MANAGER	  4900
_dept	PRESIDENT	4000
_dept	SALESMAN	23110
_dept	_job	    51474
*/

/*
2.Rank的用法 
      功能描述:根据ORDER BY子句中表达式的值,从查询返回的每一行,计算它们与其它行的相对位置。
      组内的数据按ORDER BY子句排序,然后给每一行赋一个号,从而形成一个序列,该序列从1开始,往后累加。
      每次ORDER BY表达式的值发生变化时,该序列也随之增加。有同样值的行得到同样的数字序号(认为null时相等的)。
      然而,如果两行的确得到同样的排序,则序数将随后跳跃。若两行序数为1,则没有序数2,序列将给组中的下一行分配值3,
      DENSE_RANK则没有任何跳跃。 
      rank()是跳跃排序,比如有两个第二名时接下来就是第四名(同样是在各个分组内) 
      dense_rank()是连续排序,比如有两个第二名时仍然跟着第三名。 
*/
Select nvl(to_char(deptno), 'all_dept') deptno,
       Sum(sal) n_sal,
       rank() over(Order By Sum(sal) Desc) n_rank,
       dense_rank() over(Order By Sum(sal) Desc) n_dense_rank
  From emp
 Group By deptno;
/*
30	31110	1	1
20	11023	2	2
10	9341	3	3
*/

/*
3.First/Last的用法 
     First功能描述:从DENSE_RANK返回的集合中取出排在最前面的一个值的行(可能多行,因为值可能相等),
     因此完整的语法需要在开始处加上一个集合函数以从中取出记录。 
     Last功能描述:从DENSE_RANK返回的集合中取出排在最后面的一个值的行(可能多行,因为值可能相等),
     因此完整的语法需要在开始处加上一个集合函数以从中取出记录。 
*/
Select ename,
       deptno,
       sal,
       Min(sal) keep(dense_rank First Order By deptno asc) over(Partition By deptno) "Worst",
       Max(sal) keep(dense_rank Last Order By deptno asc) over(Partition By deptno) "Best"
  From emp
 Order By deptno, sal;

/*
MILLER	 10	 111.00	  111	  4000
CLARK	   10	 2000.00	111	  4000
SMITH	   10	 3230.00	111	  4000
KING	   10	 4000.00	111	  4000
FORD	   20	 123.00	  123	  6000
JONES	   20	 1900.00	123	  6000
SCOTT	   20	 3000.00	123	  6000
ADAMS	   20	 6000.00	123	  6000
BLAKE	   30	 1000.00	1000	9000
ALLEN	   30	 1110.00	1000	9000
MARTIN	 30	 5000.00	1000	9000
JAMES	   30	 7000.00	1000	9000
TURNER	 30	 8000.00	1000	9000
WARD	   30	 9000.00	1000	9000
*/



/*
4.FIRST_VALUE/LAST_VALUE的用法 
     FIRST_VALUE、LAST_VALUE是两个分析函数。
     返回结果集中排在第一位和最后一位的值。语法是: 
     FIRST_VALUE (expr) OVER ( analytic_clause) 
*/
Select deptno,
       ename,
       sal,
       first_value(ename) over(Partition By deptno Order By sal Desc rows Between unbounded preceding And unbounded following) As rich_emp,
       last_value(ename) over(Partition By deptno Order By sal Desc rows Between unbounded preceding And unbounded following) As poor_emp
  From emp
 Order By deptno, sal;

/*
10	MILLER	111.00	 KING	  MILLER
10	CLARK	  2000.00	 KING	  MILLER
10	SMITH	  3230.00	 KING	  MILLER
10	KING	  4000.00	 KING	  MILLER
20	FORD	  123.00	 ADAMS	FORD
20	JONES	  1900.00	 ADAMS	FORD
20	SCOTT	  3000.00	 ADAMS	FORD
20	ADAMS	  6000.00	 ADAMS	FORD
30	BLAKE	  1000.00	 WARD	  BLAKE
30	ALLEN	  1110.00	 WARD	  BLAKE
30	MARTIN	5000.00	 WARD	  BLAKE
30	JAMES	  7000.00	 WARD	  BLAKE
30	TURNER	8000.00	 WARD	  BLAKE
30	WARD	  9000.00	 WARD	  BLAKE
*/

/*
5.Lag/Lead的用法 
     功能描述:可以访问结果集中的其它行而不用进行自连接。
     它允许去处理游标,就好像游标是一个数组一样。
     在给定组中可参考当前行之前的行,这样就可以从组中与当前行一起选择以前的行。
     Offset是一个正整数,其默认值为1,若索引超出窗口的范围,就返回默认值(默认返回的是组中第一行),其相反的函数是LEAD。 
*/
Select deptno,
       ename,
       sal,
       lag(sal) over(Partition By deptno Order By sal desc) As lag_sal,
       lead(sal) over(Partition By deptno Order By sal desc) As lead_sal
  From emp
 Order By deptno, sal desc;
/*
10	KING	  4000.00	 	     3230
10	SMITH	  3230.00	 4000	 2000
10	CLARK	  2000.00	 3230	 111
10	MILLER	111.00	 2000	 
20	ADAMS	  6000.00	 	     3000
20	SCOTT	  3000.00	 6000	 1900
20	JONES	  1900.00	 3000	 123
20	FORD	  123.00	 1900	
30	WARD	  9000.00	     	 8000
30	TURNER	8000.00	 9000	 7000
30	JAMES	  7000.00	 8000	 5000
30	MARTIN	5000.00	 7000	 1110
30	ALLEN	  1110.00	 5000	 1000
30	BLAKE	  1000.00	 1110	 
*/

/*
6.RATIO_TO_REPORT用法 
      功能描述:该函数计算expression/(sum(expression))的值,
      它给出相对于总数的百分比,即当前行对sum(expression)的贡献。 
      格式:RATIO_TO_REPORT (expr) OVER (query_partition_clause) */

Select deptno, ename, sal, ratio_to_report(sal) over(Partition By deptno)
  From emp
 Order By deptno, sal Desc;
/*
10	KING	4000.00	0.428219676694144
10	SMITH	3230.00	0.345787388930521
10	CLARK	2000.00	0.214109838347072
10	MILLER	111.00	0.0118830960282625
20	ADAMS	6000.00	0.544316429284224
20	SCOTT	3000.00	0.272158214642112
20	JONES	1900.00	0.172366869273338
20	FORD	123.00	0.0111584868003266
30	WARD	9000.00	0.289296046287367
30	TURNER	8000.00	0.257152041144327
30	JAMES	7000.00	0.225008036001286
30	MARTIN	5000.00	0.160720025715204
30	ALLEN	1110.00	0.0356798457087753
30	BLAKE	1000.00	0.0321440051430408
*/

/*
7.GROUPING SETS用法 
    从Oracle9i开始,使用GROUPING SETS操作符可以合并多个分组的结果。
    并且可以用GROUP BY GROUPING SETS来代替GROUP BY CUBE。
    你可以应用来指定你感兴趣的总数组合。
    因为它不必计算它不需要集合(也不会产生太多结果),所以对SQL引擎来说更为高效。 
*/
Select decode(Grouping(deptno), 1, '_dept', to_char(deptno)) deptno,
      decode(Grouping(job), 1, '_job', to_char(job)) job,
      Sum(sal)
 From emp
Group By Grouping Sets(deptno, job)
Order By deptno, job;

/*
10	  _job	    9341
20	  _job	    11023
30	  _job	    31110
_dept	ANALYST	  3123
_dept	CLERK	    16341
_dept	MANAGER	  4900
_dept	PRESIDENT	4000
_dept	SALESMAN	23110
*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值