`
lzkyo
  • 浏览: 463828 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

oracle 统计/分析函数

阅读更多

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

语法:

Sql代码 复制代码
  1. <analytic-function>(<argument>,<argument>,...)    
  2. over(    
  3. <query-partition-clause>    
  4. <order-by-clause>    
  5. <windowing-clause>    
  6. )   
<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)每行对应的数据窗口是从第一行到最后一行,等效: 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,'合计'));  
select nvl(area_code,'合计') area_code,sum(local_fare) local_fare
 from t
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;  
select area_code,bill_month,sum(local_fare) local_fare
from t
group by cube(area_code,bill_month)
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;  
select decode(grouping(area_code),1,'all area',to_char(area_code)) area_code,
 decode(grouping(bill_month),1,'all month',bill_month) bill_month,
 sum(local_fare) local_fare
from t
group by cube(area_code,bill_month)
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;  
select area_code,sum(local_fare) local_fare,
rank() over (order by sum(local_fare) desc) fare_rank
from t
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;  
select area_code,sum(local_fare) local_fare,
dense_rank() over (order by sum(local_fare) desc ) fare_rank
from t
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;  
select area_code,sum(local_fare) local_fare,
row_number() over (order by sum(local_fare) desc ) fare_rank
from t
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;  
select user_id,tele_num,user_name,user_status,create_date 
from (
select user_id,tele_num,user_name,user_status,create_date,
rank() over (order by create_date desc) add_rank
from user_info
)
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. );  
delete from t1 where rowid in (
select row_id from (
select rowid row_id,row_number() over (partition by obj# order by rowid ) rn
) where rn <> 1
);


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  
select bill_month,area_code,sum(local_fare) local_fare,
 rank() over (partition by bill_month order by sum(local_fare) desc) area_rank
 from t
 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;  
SELECT last_name, department_id, salary,
MIN(salary) KEEP (DENSE_RANK FIRST ORDER BY commission_pct)
OVER (PARTITION BY department_id) "Worst",
MAX(salary) KEEP (DENSE_RANK LAST ORDER BY commission_pct)
OVER (PARTITION BY department_id) "Best"
FROM employees
WHERE department_id in (20,80)
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);  
SELECT department_id, last_name, salary, FIRST_VALUE(last_name)
OVER (PARTITION BY department_id ORDER BY salary ASC ) AS lowest_sal
FROM employees
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   
  10.  )  
select area_code,bill_month, local_fare cur_local_fare,
 lag(local_fare,2,0) over (partition by area_code order by bill_month ) pre_local_fare,
 lag(local_fare,1,0) over (partition by area_code order by bill_month ) last_local_fare,
 lead(local_fare,1,0) over (partition by area_code order by bill_month ) next_local_fare,
 lead(local_fare,2,0) over (partition by area_code order by bill_month ) post_local_fare
 from (
 select area_code,bill_month,sum(local_fare) local_fare
 from t
 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';  
SELECT last_name, salary, RATIO_TO_REPORT(salary) OVER () AS rr
FROM employees
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. );  
SELECT prod_id, cust_id, channel_id, SUM(quantity_sold)
FROM sales
WHERE cust_id < 3
GROUP BY GROUPING SETS (
(prod_id), (cust_id, channel_id) ,NULL
);


示例:统计人员的获奖数

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)  
分享到:
评论

相关推荐

    oracle10g之统计与分析函数

    Oracle 10g 提供了一系列强大的统计与分析函数,这些函数极大地增强了数据库系统对业务数据的计算和统计能力。在10g版本中,引入了一些新的功能,使得数据分析更为便捷和高效。以下是对这些函数的详细说明: 1. **...

    OraclePl/sal

    - **复杂数学运算**:实现复杂数学运算,如统计分析等。 #### 4. 触发器与存储过程结合使用 - **实现高级逻辑**:结合使用触发器和存储过程可以实现更为复杂的业务逻辑处理。 ### 四、Oracle PL/SQL 10g的开发实践...

    ORACLE分析函数大全

    在实际应用中,Oracle分析函数可以帮助我们编写出更复杂的查询,比如计算移动平均、计算等级分、以及在时间序列数据上执行各种统计分析。理解和熟练掌握这些函数可以极大地提升SQL查询的灵活性和效率,对于数据分析...

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

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

    oracle 分析函数学习笔记

    在描述中提到的场景中,有几种不同的方法可以实现数据统计,包括通过程序处理、使用临时表和包、标准SQL的UNION以及Oracle特有的分析函数。每种方法都有其优缺点。例如,程序处理方法与数据库无关,但增加了开发工作...

    ORACLE 分析函数大全

    Oracle 分析函数是一种强大的SQL工具,它允许你在处理数据时执行复杂的分析操作,而不像聚合函数那样仅仅返回单行结果。分析函数在Oracle 8.1.6版本中被引入,自那时起,它们已经成为数据库查询和报表生成的重要组成...

    Oracle PL/SQL常用47个工具包

    17. **DBMS_CRYPTO**: 提供加密和哈希函数,用于数据安全。 18. **DBMS_STATS.GATHER_SCHEMA_STATS**: 收集整个模式的统计信息,优化性能。 19. **DBMS_PROFILER**: 性能分析工具,追踪PL/SQL代码的执行时间。 20...

    Oracle分析函数

    #### 四、统计分析函数 ##### 1. STDDEV / STDDEV_POP / STDDEV_SAMP - **定义**:计算标准偏差。 - **用途**:适用于需要衡量数据波动程度的场景。 ##### 2. VAR_POP / VAR_SAMP / VARIANCE - **定义**:计算方差...

    oracle分析函数及开窗函数

    ### Oracle分析函数及开窗函数详解 #### 一、Oracle分析函数概述 Oracle自8.1.6版本开始引入了分析函数,这类函数主要用于计算基于组的聚合值,并且与传统的聚合函数不同的是,分析函数可以针对每个组返回多行结果...

    ORACLE报表分析利剑——分析函数

    分析函数作为Oracle数据库中一项高级功能,专为解决复杂报表统计需求设计,其核心优势在于能够对数据进行精细的分组处理后,计算基于这些分组的特定统计值。与传统的聚合函数不同,分析函数不仅能够实现分组统计,还...

    Oracle分析函数教程

    这使得分析函数在数据分析和报表生成方面非常有用,能够处理更复杂的统计和排序需求。 分析函数的主要特点在于其数据窗口的概念。数据窗口定义了函数作用的行集范围,可以基于排序、分组或者特定的行数或范围来定义...

    Oracle分析函数.pdf

    Oracle分析函数是Oracle数据库提供的用于数据分析的一组SQL扩展,它们能够对一组数据执行计算,并返回一组结果,这组结果通常会有一个多行的集合。与聚合函数不同,分析函数不会把多行聚合成单一结果,而是在原有...

    oracle分析函数全面解析

    Oracle分析函数是数据库管理系统Oracle中的一种高级查询工具,主要用于处理复杂的报表统计和数据分析。它们在OLAP(在线分析处理)系统中尤其重要,因为这类系统往往需要处理大量数据并进行复杂的聚合计算,而分析...

    ORACLE分析函数.ppt

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

    oracle分析函数

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

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

    ### Oracle的分析函数OVER及开窗函数 #### 一、分析函数OVER ##### 1. 概念介绍 从Oracle 8.1.6版本开始,Oracle引入了分析函数,这些函数可以对分组的数据执行复杂的操作,如计算累积总和、排名等。与聚合函数...

Global site tag (gtag.js) - Google Analytics