`

ORACLE 分析函数解析

阅读更多
分析函数是oracle 8.1.6中就引入的一个全新的概念,为我们分析数据提供了一种简单高效的处理方式.在分析函数出现以前,我们必须使用自联查询,子查询或者内联视图,甚至复杂的存储过程实现的语句,现在只要一条简单的sql语句就可以实现了,而且在执行效率方面也有相当大的提高.
而ORACLE的常见分析函数有三类:
1. OVER函数
   分析函数的语法为:
 
 FUNCTION_NAME(<argument>,<argument>...)
    OVER
    (<Partition-Clause><Order-by-Clause><Windowing Clause>)

   例:
   sum(sal) over (partition by deptno order by ename) new_alias
   sum就是函数名
  (sal)是分析函数的参数,每个函数有0~3个参数,参数可以是表达式,例如:sum(sal+comm)
   over 是一个关键字,用于标识分析函数,否则查询分析器不能区别sum()聚集函数和sum()分析函数
   partition by deptno 是可选的分区子句,如果不存在任何分区子句,则全部的结果集可看作一   个单一的大区
   order by ename 是可选的order by 子句,有些函数需要它,有些则不需要.依靠已排序数据的那些函数,如:用于访问结果集中前一行和后一行的LAG和LEAD,必须使用,其它函数,如AVG,则不需要.在使用了任何排序的开窗函数时,该子句是强制性的,它指定了在计算分析函数时一组内的数据是如何排序的.
  eg:按区域查找上一年度订单总额占区域订单总额20%以上的客户,来看看分析函数的应用。
  【1】测试环境:
SQL> desc orders_tmp;
  Name                           Null?    Type
  ----------------------- -------- ----------------
  CUST_NBR                    NOT NULL NUMBER(5)
  REGION_ID                   NOT NULL NUMBER(5)
  SALESPERSON_ID      NOT NULL NUMBER(5)
  YEAR                              NOT NULL NUMBER(4)
  MONTH                         NOT NULL NUMBER(2)
  TOT_ORDERS              NOT NULL NUMBER(7)
  TOT_SALES                 NOT NULL NUMBER(11,2)

【2】测试数据:
 SQL> select * from orders_tmp;
 
   CUST_NBR  REGION_ID SALESPERSON_ID       YEAR      MONTH TOT_ORDERS  TOT_SALES
 ---------- ---------- -------------- ---------- ---------- ---------- ----------
         11          7             11                       2001          7          2      12204
          4          5              4                         2001         10         2      37802
          7          6              7                         2001          2          3       3750
         10          6              8                        2001          1          2      21691
         10          6              7                        2001          2          3      42624
         15          7             12                       2000          5          6         24
         12          7              9                        2000          6          2      50658
          1          5              2                         2000          3          2      44494
          1          5              1                         2000          9          2      74864
          2          5              4                         2000          3          2      35060
          2          5              4                         2000          4          4       6454
          2          5              1                         2000         10          4      35580
          4          5              4                         2000         12          2      39190
 
 13 rows selected.

【3】测试语句:
 SQL> select o.cust_nbr customer,
   2         o.region_id region,
   3         sum(o.tot_sales) cust_sales,
   4         [color=red]sum(sum(o.tot_sales)) over(partition by o.region_id) region_sales
[/color]   5    from orders_tmp o
   6   where o.year = 2001
   7   [color=red]group by o.region_id, o.cust_nbr;[/color]
 
   CUSTOMER     REGION CUST_SALES REGION_SALES
 ---------- ---------- ---------- ------------
          4              5      37802        37802
          7              6       3750         68065
         10             6      64315        68065
         11             7      12204        12204

group by的意图很明显:将数据按区域ID,客户进行分组,那么Over这一部分有什么用呢?假如我们只需要统计每个区域每个客户的订单总额,那么我们只需要group by o.region_id,o.cust_nbr就够了。但我们还想在每一行显示该客户所在区域的订单总额,这一点和前面的不同:需要在前面分组的基础上按区域累加。很显然group by和sum是无法做到这一点的(因为聚集操作的级别不一样,前者是对一个客户,后者是对一批客户)。

这就是over函数的作用了!它的作用是告诉SQL引擎:按区域对数据进行分区,然后累积每个区域每个客户的订单总额(sum(sum(o.tot_sales)))。
总结:
①Over函数指明在那些字段上做分析,其内跟Partition by表示对数据进行分组。注意Partition by可以有多个字段。
②Over函数可以和其它聚集函数、分析函数搭配,起到不同的作用。例如这里的SUM,还有诸如Rank,Dense_rank等。

2. RANK,DENSE_RANK,ROW_NUMBER函数
  Rank,Dense_rank,Row_number函数为每条记录产生一个从1开始至N的自然数,N的值可能小于等于记录的总数。这3个函数的唯一区别在于当碰到相同数据时的排名策略。

①ROW_NUMBER:
Row_number函数返回一个唯一的值,当碰到相同数据时,排名按照记录集中记录的顺序依次递增。
②DENSE_RANK:
Dense_rank函数返回一个唯一的值,除非当碰到相同数据时,此时所有相同数据的排名都是一样的。
③RANK:
Rank函数返回一个唯一的值,除非遇到相同的数据时,此时所有相同数据的排名是一样的,同时会在最后一条相同记录和下一条不同记录的排名之间空出排名。
看下面一个例子:
 SQL> select region_id, customer_id, sum(customer_sales) total,
   2         rank() over(order by sum(customer_sales) desc) rank,
   3         dense_rank() over(order by sum(customer_sales) desc) dense_rank,
   4         row_number() over(order by sum(customer_sales) desc) row_number
   5    from user_order
   6   group by region_id, customer_id;
 
  REGION_ID CUSTOMER_ID      TOTAL       RANK DENSE_RANK ROW_NUMBER
 ---------- ----------- ---------- ---------- ---------- ----------
             
          8          18                1253840         11         11         11
          5           2                 1224992         12         12         12
          9          23                1224992         12         12         13
          9          24                1224992         12         12         14
         10          30               1216858         15           13            15
     
 
 30 rows selected.

 
3. TOP/BOTTOM N,FIRST/LAST,NTILE,NULLS LAST
  1)NULLS LAST:
 SQL> select region_id, customer_id,
   2         sum(customer_sales) cust_total,
   3         sum(sum(customer_sales)) over(partition by region_id) reg_total,
   4         rank() over(partition by region_id 
                        order by sum(customer_sales) desc NULLS LAST) rank
   5        from user_order
   6       group by region_id, customer_id;
 
  REGION_ID CUSTOMER_ID CUST_TOTAL  REG_TOTAL       RANK
 ---------- ----------- ---------- ---------- ----------
         10          26    1808949     6238901           1
         10          27    1322747    6238901           2
         10          30    1216858    6238901           3
         10          28     986964     6238901           4
         10          29     903383     6238901           5
         10          31     6238901                           6

NULLS LAST/FIRST告诉Oracle让空值排名最后后第一。注意是NULLS,不是NULL。
2).TOP N/BOTTOM N:
  eg:找出每个区域订单总额排名前3的大客户:
SQL> select *
   2    from (select region_id,
   3                 customer_id,
   4                 sum(customer_sales) cust_total,
   5                 sum(sum(customer_sales)) over(partition by region_id) reg_total,
   6                 rank() over(partition by region_id
                                order by sum(customer_sales) desc NULLS LAST) rank
   7            from user_order
   8           group by region_id, customer_id)
   9   where rank <= 3;
 
  REGION_ID CUSTOMER_ID CUST_TOTAL  REG_TOTAL       RANK
 ---------- ----------- ---------- ---------- ----------
          5           4    1878275    5585641          1
          5           2    1224992    5585641          2
          5           5    1169926    5585641          3
          6           6    1788836    6307766          1
          6           9    1208959    6307766          2
          6          10    1196748    6307766          3
          7          14    1929774    6868495          1
          7          13    1310434    6868495          2
          7          15    1255591    6868495          3
          8          17    1944281    6854731          1
          8          20    1413722    6854731          2
          8          18    1253840    6854731          3
          9          25    2232703    6739374          1
          9          23    1224992    6739374          2
          9          24    1224992    6739374          2
         10          26    1808949    6238901          1
         10          27    1322747    6238901          2
         10          30    1216858    6238901          3
 
 18 rows selected.

  3). FIRST / LAST:
   eg:找出订单总额最多、最少的客户
 
SQL> select min(customer_id)
   2         keep (dense_rank first order by sum(customer_sales) desc) first,
   3         min(customer_id)
   4         keep (dense_rank last order by sum(customer_sales) desc) last
   5    from user_order
   6   group by customer_id;
 
      FIRST       LAST
 ---------- ----------
         31          1

4) NTILE---按层次查询
eg:找出订单总额排名前1/5的客户
SQL> select region_id,
   2         customer_id,
   3         ntile(5) over(order by sum(customer_sales) desc) til
   4    from user_order
   5   group by region_id, customer_id;
 
  REGION_ID CUSTOMER_ID       TILE
 ---------- ----------- ----------
         10          31          1
          9          25           1
         10          26          1
          6           6            1         
          8          18           2
          5           2            2
          9          23           3
          6           9            3
          7          11           3
          5           3            4
          6           8            4
          8          16           4
          6           7            5
         10          29          5
          5           1            5

Ntil函数为各个记录在记录集中的排名计算比例,我们看到所有的记录被分成5个等级,那么假如我们只需要前1/5的记录则只需要截取TILE的值为1的记录就可以了。假如我们需要排名前25%的记录(也就是1/4)那么我们只需要设置ntile(4)就可以了。
分享到:
评论

相关推荐

    oracle分析函数全面解析

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

    oracle分析函数.doc

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

    oracle分析函数,窗口函数,报表函数

    分析函数 `OVER` 解析 `OVER`子句可以配合以下部分使用: - **PARTITION BY**:根据指定的列将数据分为多个分区,每个分区内的计算是独立的。 - **ORDER BY**:在每个分区内部按指定的列排序,这对于计算排名或...

    oracle分析函数及开窗函数

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

    oracle分析函数学习

    Oracle分析函数是数据库查询中的重要工具,特别是在处理复杂的报表和数据分析任务时,它们能提供强大的功能,帮助开发者高效地处理大量数据。分析函数允许你在数据集上执行计算,同时考虑到行之间的关系,而不仅仅是...

    oracle分析函数指南

    Oracle分析函数是数据库查询中的重要工具,主要用于处理复杂的聚合和排序操作,特别是在OLAP(在线分析处理)系统中,它们能够高效地进行数据汇总和分析。分析函数与聚合函数(如SUM, AVG, COUNT等)有所不同,聚合...

    分析函数详细解析

    ### 分析函数详细解析 #### 一、概述 ##### 1.1 什么是分析函数 随着信息技术的发展,企业对数据的依赖程度日益增加。在信息化初期,数据收集成为了首要任务,因为“无数据,不真实”的理念深入人心。然而,随着...

    oracle分析函数

    Oracle分析函数是数据库查询中的一个重要工具,主要用于处理复杂的分组和排序数据,提供了一种高效的方式来计算基于数据集的聚合信息。在OLAP(在线分析处理)系统中,分析函数尤其重要,因为它们能帮助用户在大数据...

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

    ### ORACLE报表分析利剑——分析函数:深度解析与应用 #### 一、理解分析函数:数据统计的新维度 分析函数作为Oracle数据库中一项高级功能,专为解决复杂报表统计需求设计,其核心优势在于能够对数据进行精细的...

    Oracle 分析函数

    ### Oracle分析函数详解 #### 一、Oracle分析函数简介 Oracle分析函数是在Oracle数据库中用于处理复杂的查询需求的一组强大的工具。与传统的SQL聚合函数(如`SUM`, `AVG`, `COUNT`等)不同,分析函数能够在同一...

    Oracle函数大全-详细介绍.rar

    "oracle函数介绍(6) 著名函数之分析函数.doc","oracle函数介绍(7) 非著名函数之分析函数.doc"以及"oracle分析函数.doc"深入介绍了这些高级函数,帮助理解如何利用它们进行复杂的数据分析。 最后,"oracle函数介绍...

    Oracle内置函数大全

    在Oracle中,日期格式和数字格式的说明符是处理数据的关键工具,它们决定了如何显示和解析日期和数字。 日期格式元素主要用于定义日期和时间的显示样式。例如,`TO_DATE`函数在转换字符串为日期时就需要一个日期...

    Oracle百分比分析函数RATIO_TO_REPORT() OVER()实例详解

    Oracle数据库中的RATIO_TO_REPORT()函数是一个非常有用的分析函数,尤其在进行数据比例分析和比较时。这个函数能够计算一个值相对于所有值总和的比例,返回的结果是一个百分比。配合OVER()子句,它可以用于全局或者...

    Oracle分析函数使用的总结.doc

    本文将详细介绍Oracle分析函数中的评级函数,包括RANK()、DENSE_RANK()、CUME_DIST()、PERCENT_RANK()和NTILE(),并结合示例进行解析。 1. RANK()函数: RANK()函数返回每个行在指定排序下的排名。如果两个或更多...

    Oracle 高级查询之分析函数部分--first_value,last_value

    ### Oracle分析函数:`FIRST_VALUE()`和`LAST_VALUE()` #### `FIRST_VALUE()`函数 `FIRST_VALUE()`函数返回在一个窗口函数中定义的顺序下,指定列的首个值。这通常用于返回一个分组内按照某种顺序(如按时间、数值...

Global site tag (gtag.js) - Google Analytics