`

oracle分析函数(2)

阅读更多
注意这里有3条记录的订单总额是一样的。假如我们现在需要筛选排名前12位的客户,如果使用rownum会有什么样的后果呢?

SQL >   select  rownum, t. *
    2      from  ( select   * 
    3              from  user_order
    4             order   by  customer_sales  desc ) t
    5     where  rownum  <=   12
    6     order   by  customer_sales  desc ;

     ROWNUM  REGION_ID CUSTOMER_ID CUSTOMER_SALES
-- -------- ---------- ----------- --------------
           1            9                  25          2232703
           2            8                  17          1944281
           3            7                   14          1929774
           4            5                     4          1878275
           5           10                  26          1808949
           6            6                    6          1788836
           7            8                  20          1413722
           8           10                 27          1322747
           9            7                 13          1310434
          10            7                15          1255591
          11            8                18          1253840
          12              5                      2           1224992

12  rows selected.

很明显假如只是简单地按rownum进行排序的话,我们漏掉了另外两条记录(参考上面的结果)。

二、使用分析函数来为记录排名:

针对上面的情况,Oracle从8i开始就提供了3个分析函数:rand,dense_rank,row_number来解决诸如此类的问题,下面我们来看看这3个分析函数的作用以及彼此之间的区别:

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

①ROW_NUMBER:



Row_number函数返回一个唯一的值,当碰到相同数据时,排名按照记录集中记录的顺序依次递增。 

②DENSE_RANK:
Dense_rank函数返回一个唯一的值,除非当碰到相同数据时,此时所有相同数据的排名都是一样的。 

③RANK:
Rank函数返回一个唯一的值,除非遇到相同的数据时,此时所有相同数据的排名是一样的,同时会在最后一条相同记录和下一条不同记录的排名之间空出排名。

这样的介绍有点难懂,我们还是通过实例来说明吧,下面的例子演示了3个不同函数在遇到相同数据时不同排名策略:

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种不同的排名策略:

①对于第一条相同的记录,3种函数的排名都是一样的:12

②当出现第二条相同的记录时,Rank和Dense_rank依然给出同样的排名12;而row_number则顺延递增为13,依次类推至第三条相同的记录

③当排名进行到下一条不同的记录时,可以看到Rank函数在12和15之间空出了13,14的排名,因为这2个排名实际上已经被第二、三条相同的记录占了。而Dense_rank则顺序递增。row_number函数也是顺序递增

比较上面3种不同的策略,我们在选择的时候就要根据客户的需求来定夺了:

①假如客户就只需要指定数目的记录,那么采用row_number是最简单的,但有漏掉的记录的危险

②假如客户需要所有达到排名水平的记录,那么采用rank或dense_rank是不错的选择。至于选择哪一种则看客户的需要,选择dense_rank或得到最大的记录

三、使用分析函数为记录进行分组排名:

上面的排名是按订单总额来进行排列的,现在跟进一步:假如是为各个地区的订单总额进行排名呢?这意味着又多了一次分组操作:对记录按地区分组然后进行排名。幸亏Oracle也提供了这样的支持,我们所要做的仅仅是在over函数中order by的前面增加一个分组子句:partition by region_id。

SQL >   select  region_id, customer_id,
                sum (customer_sales) total,
    2          rank()  over (partition  by  region_id
                         order   by   sum (customer_sales)  desc ) rank,
    3          dense_rank()  over (partition  by  region_id
                         order   by   sum (customer_sales)  desc ) dense_rank,
    4          row_number()  over (partition  by  region_id
                         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
-- -------- ----------- ---------- ---------- ---------- ----------
           5             4                  1878275            1            1            1
           5             2                 1224992            2            2            2
           5             5                 1169926            3            3            3
           6             6                 1788836            1            1            1
           6             9                 1208959            2            2            2
           6            10                 1196748            3            3            3       
   

30  rows selected.

现在我们看到的排名将是基于各个地区的,而非所有区域的了!Partition by 子句在排列函数中的作用是将一个结果集划分成几个部分,这样排列函数就能够应用于这各个子集。

三.分析函数3(top\bottom n、first\last、ntile)


目录
===============================================
1.带空值的排列
2.Top/Bottom N查询
3.First/Last排名查询
4.按层次查询

一、带空值的排列:

在前面《Oracle开发专题之:分析函数2(Rank、Dense_rank、row_number) 》一文中,我们已经知道了如何为一批记录进行全排列、分组排列。假如被排列的数据中含有空值呢?

SQL >   select  region_id, customer_id,
    2           sum (customer_sales) cust_sales,
    3           sum ( sum (customer_sales))  over (partition  by  region_id) ran_total,
    4          rank()  over (partition  by  region_id
    5                    order   by   sum (customer_sales)  desc ) rank
    6      from  user_order
    7     group   by  region_id, customer_id;

  REGION_ID CUSTOMER_ID CUST_SALES  RAN_TOTAL       RANK
-- -------- ----------- ---------- ---------- ---------- 
          10            31                     6238901            1
          10            26      1808949      6238901            2
          10            27      1322747      6238901            3
          10            30      1216858      6238901            4
          10            28       986964      6238901            5
          10            29       903383      6238901            6
我们看到这里有一条记录的CUST_TOTAL字段值为NULL,但居然排在第一名了!显然这不符合情理。所以我们重新调整完善一下我们的排名策略,看看下面的语句:

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。

二、Top/Bottom N查询:

在日常的工作生产中,我们经常碰到这样的查询:找出排名前5位的订单客户、找出排名前10位的销售人员等等。现在这个对我们来说已经是很简单的问题了。下面我们用一个实际的例子来演示:

【1】找出所有订单总额排名前3的大客户:

SQL >   select   *
SQL >     from  ( select  region_id,
SQL >                 customer_id,
SQL >                  sum (customer_sales) cust_total,
SQL >                 rank() over ( order   by   sum (customer_sales)  desc  NULLS LAST) rank
SQL >             from  user_order
SQL >            group   by  region_id, customer_id)
SQL >    where  rank  <=   3 ;

  REGION_ID CUSTOMER_ID CUST_TOTAL       RANK
-- -------- ----------- ---------- ----------
           9            25      2232703            1
           8            17      1944281            2
           7            14      1929774            3

SQL >  


分享到:
评论

相关推荐

    ORACLE分析函数教程

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

    Oracle中的分析函数详解

    其中,Oracle的分析函数是其强大的特性之一,它允许用户在单个SQL查询中执行复杂的分析操作,而无需使用子查询或者自连接。这篇文档将深入探讨Oracle中的分析函数,帮助你更好地理解和利用这一功能。 一、什么是...

    oracle分析函数文档

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

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

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

    ORACLE分析函数大全

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

    ORACLE 分析函数大全

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

    Oracle分析函数

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

    oracle 分析函数学习笔记

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

    oracle 分析函数

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

    oracle分析函数大全

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

    Oracle分析函数.doc

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

    ORACLE分析函数.pdf

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

    Oracle分析函数使用总结

    Oracle分析函数使用总结Oracle分析函数使用总结Oracle分析函数使用总结Oracle分析函数使用总结

    oracle分析函数.doc

    2. **Oracle分析函数简单实例** 假设我们有一个销售表,包含产品ID、销售日期和销售额,我们可以使用`ROW_NUMBER()`来为每条记录分配一个顺序编号,或者使用`SUM()`函数计算每个产品的累计销售额。 ```sql ...

    Oracle 分析函数.doc

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

    ORACLE 常用分析函数

    分析函数2(Rank, Dense_rank, row_number);分析函数3(Top/Bottom N、First/Last、NTile);窗口函数;报表函数;分析函数总结;26个分析函数;PLSQL开发笔记和小结;分析函数简述  ROW_NUMBER () OVER([partition_clause]...

    ORACLE_分析函数大全

    Oracle分析函数是数据库管理系统Oracle中的一种高级SQL特性,它们在数据处理和分析中扮演着重要角色。分析函数允许用户在结果集的每一行上执行计算,不仅考虑当前行,还考虑了同一组内的其他行。这与传统的聚合函数...

    Oracle分析函数教程

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

    ORACLE分析函数.ppt

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

Global site tag (gtag.js) - Google Analytics