`
atoooo
  • 浏览: 13192 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

rank over partition dense_rank() row_number()

阅读更多

排列(rank())函数。这些排列函数提供了定义一个集合(使用 PARTITION 子句),然后根据某种排序方式对这个集合内的元素进行排列的能力,下面以scott用户的emp表为例来说明rank over partition如何使用

1)查询员工薪水并连续求和

select deptno,ename,sal,

sum(sal)over(order by ename) sum1,  /*表示连续求和*/
sum(sal)over() sum2,                          /*相当于求和sum(sal)*/
100* round(sal/sum(sal)over(),4) "bal%"
from emp

结果如下:

    DEPTNO ENAME            SAL      SUM1      SUM2      bal%
---------- ---------- ---------- ---------- ---------- ----------
        20 ADAMS            1100      1100      29025      3.79
        30 ALLEN            1600      2700      29025      5.51
        30 BLAKE            2850      5550      29025      9.82
        10 CLARK            2450      8000      29025      8.44
        20 FORD            3000      11000      29025      10.34
        30 JAMES            950      11950      29025      3.27
        20 JONES            2975      14925      29025      10.25
        10 KING            5000      19925      29025      17.23
        30 MARTIN          1250      21175      29025      4.31
        10 MILLER          1300      22475      29025      4.48
        20 SCOTT            3000      25475      29025      10.34

    DEPTNO ENAME            SAL      SUM1      SUM2      bal%
---------- ---------- ---------- ---------- ---------- ----------
        20 SMITH            800      26275      29025      2.76
        30 TURNER          1500      27775      29025      5.17
        30 WARD            1250      29025      29025      4.31

2)如下:

select deptno,ename,sal,
sum(sal)over(partition by deptno order by ename) sum1,/*表示按部门号分氏,按姓名排序并连续求和*/
sum(sal)over(partition by deptno) sum2,/*表示部门分区,求和*/
sum(sal)over(partition by deptno order by sal) sum3,/*按部门分区,按薪水排序并连续求和*/
100* round(sal/sum(sal)over(),4) "bal%"
from emp

结果如下:

    DEPTNO ENAME            SAL      SUM1      SUM2      SUM3      bal%
---------- ---------- ---------- ---------- ---------- ---------- ----------
        10 CLARK            2450      2450      8750      3750      8.44
        10 KING            5000      7450      8750      8750      17.23
        10 MILLER          1300      8750      8750      1300      4.48
        20 ADAMS            1100      1100      10875      1900      3.79
        20 FORD            3000      4100      10875      10875      10.34
        20 JONES            2975      7075      10875      4875      10.25
        20 SCOTT            3000      10075      10875      10875      10.34
        20 SMITH            800      10875      10875        800      2.76
        30 ALLEN            1600      1600      9400      6550      5.51
        30 BLAKE            2850      4450      9400      9400      9.82
        30 JAMES            950      5400      9400        950      3.27

    DEPTNO ENAME            SAL      SUM1      SUM2      SUM3      bal%
---------- ---------- ---------- ---------- ---------- ---------- ----------
        30 MARTIN          1250      6650      9400      3450      4.31
        30 TURNER          1500      8150      9400      4950      5.17
        30 WARD            1250      9400      9400      3450      4.31

3)如下:

select empno,deptno,sal,
sum(sal)over(partition by deptno) "deptSum",/*按部门分区,并求和*/
rank()over(partition by deptno order by sal desc nulls last)  rank, /*按部门分区,按薪水排序并计算序号*/
dense_rank()over(partition by deptno order by sal desc nulls last) d_rank,
row_number()over(partition by deptno order by sal desc nulls last) row_rank
from emp

注:

rang()涵数主要用于排序,并给出序号

dense_rank():功能同rank()一样,区别在于,rank()对于排序并的数据给予相同序号,接下来的数据序号直接跳中跃,dense_rank()则不是,比如数据:1,2,2,4,5,6.。。。。这是rank()的形式

                                                      1,2,2,3,4,5,。。。。这是dense_rank()的形式

                                                      1,2,3,4,5,6.。。。。。这是row_number()涵数形式

row_number()涵数则是按照顺序依次使用,相当于我们普通查询里的rownum值

其实从上面三个例子当中,不难看出over(partition by ... order by ...)的整体概念,我理解是

partition by :按照指字的字段分区,如果没有则针对全体数据

order by      :按照指定字段进行连续操作(如求和(sum),排序(rank()等),如果没有指定,就相当于对指定分区集合内的数据进行整体sum操作

oracle聚合函数rank()的用法

SQL> select * from test_a;

ID                  PLAYNAME                  SCORE

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

01                  aa                          100

02                  aa                          101

02                  bb                          99

03                  bb                          98

04                  aa                          101

02                  aa                          101

需求是,将score降序排序,打印所有字段,并且如果是同一个playname的score只取出最高分,如果这个playname获得过多个相同的最高分,则只取出其中一个(比如:aa获得过3次101,则只取其中一个),最终要的结果就是:

        RK ID                  PALYNAME                  SCORE

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

        1 02                  aa                          101

        1 02                  bb                          99

本来我想用max函数,结果直接就出来了:

SQL> select max(score),palyname from test_a group by palyname;

MAX(SCORE) PALYNAME

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

      101 aa

        99 bb

但是要打印所有字段…OTL

即使用了嵌套,还是无法解决重复重现最高分的现象:

SQL> select distinct * from test_a t where  score  in  (select  max(score)  from  test_a  group  by  palyname) order by score desc;

ID                  PALYNAME                  SCORE

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

02                  aa                          101

04                  aa                          101

02                  bb                          99

由于相同的playname对应的id不同,所以用distinct也无法过滤掉相同playname的并列最高分。

于是只好用rank()了

Rank的基本语法为:

RANK ( ) OVER ( order_by_clause )

例子1:

  

  TABLE:A (科目,分数)

  

  数学,80

  语文,70

  数学,90

  数学,60

  数学,100

  语文,88

  语文,65

  语文,77

  

  现在我想要的结果是:(即想要每门科目的前3名的分数)

  

  数学,100

  数学,90

  数学,80

  语文,88

  语文,77

  语文,70

  

  那么语句就这么写:

  

  select * from (select rank() over(partition by 科目 order by 分数 desc) rk,a.* from a) t

where t.rk<=3;

以科目来分组,然后以分数来排序,给排序的结果分配rank,取前三名的rank

例子2:

  

  有表Table内容如下

  

  COL1 COL2

    1 1

    2 1

    3 2

    3 1

    4 1

    4 2

    5 2

    5 2

    6 2

  

  分析功能:列出Col2分组后根据Col1排序,并生成数字列。比较实用于在成绩表中查出各科前几名的信息。

  

  SELECT a.*,RANK() OVER(PARTITION BY col2 ORDER BY col1) "Rank" FROM table a;

  

  结果如下:

  

  COL1 COL2 Rank

    1 1      1

    2 1      2

    3 1      3

    4 1      4

    3 2      1

    4 2      2

    5 2      3

    5 2      3

    6 2      5

这个例子更直观一点,根据col2分组,根据clo1排序,我们可以发现:

5 2      3

5 2      3

6 2      5

即,如果两行记录完全相同,他们会被给予相同的rank,而排在它们之后的那行记录,由于前面的并列第3,使得之后的那条记录变成了第5,而如果我们在这里用的是dense_rank,那么之后的那条会变成第4

例子3:

  

  合计功能:计算出数值(4,1)在Orade By Col1,Col2排序下的排序值,也就是col1=4,col2=1在排序以后的位置

  

  SELECT RANK(4,1) WITHIN GROUP (ORDER BY col1,col2) "Rank" FROM table;

  

  结果如下:

  Rank

  4

通过以上方法,得出col1为4,col2为1的那行数据的rank排名为多少

Dense_rank的例子:

dense_rank与rank()用法相当,但是有一个区别:dence_rank在并列关系是,相关等级不会跳过。rank则跳过

  

  例如:表

  

  A      B      C

  a     liu     wang

  a     jin     shu

  a     cai     kai

  b     yang     du

  b     lin     ying

  b     yao     cai

  b     yang     99

  

  例如:当rank时为:

  

  select m.a,m.b,m.c,rank() over(partition by a order by b) liu from test3 m

  

   A     B       C     LIU

   a     cai      kai     1

   a     jin      shu     2

   a     liu      wang     3

   b     lin      ying     1

   b     yang     du      2

   b     yang     99      2

   b     yao      cai     4

  

  而如果用dense_rank时为:

  

  select m.a,m.b,m.c,dense_rank() over(partition by a order by b) liu from test3 m

  

   A     B       C     LIU

   a     cai     kai       1

   a     jin     shu       2

   a     liu     wang          3

   b     lin     ying            1

   b     yang     du           2

   b     yang     99           2

   b     yao     cai       3

那么再回到之前的那个需求,

SQL> select distinct * from (select rank() over(partition by playname order by score desc,id) rk,t.* from test_a t) where rk=1;

        RK ID                  PLAYNAME                  SCORE

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

        1 02                  aa                          101

        1 02                  bb                          99

这里order by score desc,id  以score降序和id这两个字段排序,也就是说,正因为相同的playname对应的id不同,这样相同的playname,相同的score,但是不同的id,这样的2行数据就获得了不同的rank,而rk=1,即是只取rank=1,也就是最高分。这样就完成了需求

分享到:
评论

相关推荐

    分析函数ROW_NUMBER、RANK、DENSE_RANK的用法

    DENSE_RANK() OVER ([&lt;partition_by_clause&gt;] &lt;order_by_clause&gt;) ``` - **PARTITION BY 子句**:同ROW_NUMBER()和RANK()。 - **ORDER BY 子句**:同样也是必需的。 ##### 示例:按销售额计算密集排名 ```sql ...

    Oracle开发之分析函数(Rank, Dense_rank, row_number)

    ROW_NUMBER() OVER (PARTITION BY region_id ORDER BY customer_sales DESC) AS rank_in_region FROM user_order; ``` 这样,我们就可以在每个区域内找到销售额最高的客户,而不会因为其他区域的客户销售额相同...

    SQLSERVER 2005的ROW_NUMBER、RANK、DENSE_RANK的用法

    ROW_NUMBER() OVER (ORDER BY OrderDate) as RowNumber FROM Sales.SalesOrderHeader ) SELECT * FROM OrderedOrders WHERE RowNumber BETWEEN 50 AND 60 ``` 总结来说,ROW_NUMBER()、RANK()和DENSE_RANK()在SQL...

    ROW_NUMBER(),RANK()和DENSE_RANK()之间的区别

    ROW_NUMBER()、RANK()和DENSE_RANK()是其中的三个关键函数,它们都用于对数据进行排序并分配唯一的序列号,但各有其特点和适用场景。以下是对这三个函数的详细解释: 1. ROW_NUMBER() ROW_NUMBER()函数为每一行提供...

    oracle row_number用法

    `ROW_NUMBER()`可以与`RANK()`和`DENSE_RANK()`进行比较。这些函数都可以用来给数据排序并分配等级,但是它们在处理并列的情况时有所不同: - **Rank**:如果两个或多个行具有相同的排序值,则这些行都将获得相同...

    SQL 获取顺序号的四种方法 IDENTITYRANKDENSE RANKROW NUMBER

    SQL 获取顺序号的四种方法:IDENTITY、RANK、DENSE_RANK、ROW_NUMBER 在 SQL 中,获取顺序号是非常常见的操作。今天,我们将讨论四种获取顺序号的方法:IDENTITY、RANK、DENSE_RANK、ROW_NUMBER。每种方法都有其优...

    ORACLE 常用分析函数

     ROW_NUMBER () OVER([partition_clause] order_by_clause) dense_rank在做排序时如果遇到列有重复值,则重复值所在行的序列值相同,而其后的序列值依旧递增,rank则是重复值所在行的序列值相同,但其后的序列值从...

    hive分析函数

    本文将介绍 Hive 中的四个序列函数:NTILE、ROW_NUMBER、RANK 和 DENSE_RANK。 首先,让我们了解什么是序列函数。序列函数是 Hive 中的一种特殊函数,用于对数据进行排序和编号。序列函数可以将数据分组并对每组...

    Oracle中rank,over partition函数的使用方法

    它可以与 `RANK()`, `ROW_NUMBER()`, `DENSE_RANK()` 等函数结合使用,以在特定的行集上执行计算。 `PARTITION BY` 子句则是在每个分区内独立执行操作。它将数据集划分为多个逻辑部分,每个部分有自己的排名或计算...

    Sql Server2005对t-sql的增强之排名函数

    排名函数主要包括ROW_NUMBER、RANK、DENSE_RANK以及NTILE,它们各自有着不同的应用场景和功能。 1. NTILE函数 NTILE函数用于将一个有序分区的行分配到指定数量的组中。每个组都有一个从1开始的编号。例如,如果...

    深入探讨:oracle中row_number() over()分析函数用法

    with row_number_test as ( select 22 as a, 'twenty two' as b from dual union all select 1, 'one' from dual union all select 13, 'thirteen' from dual union all select 5, 'five' from dual union all ...

    oracle排名函数的使用方法分享

    在oracle中,有rank,dense_rank,row_number,以及分组排名partition。 说明: rank:排名会出现并列第n名,它之后的会跳过空出的名次,例如:1,2,2,4 dense_rank:排名会出现并列第n名,它之后的名次为n+1,例如:1,2,...

    ORACLE分析函数.pdf

    2. 排序函数 (RANK, DENSE_RANK, ROW_NUMBER) 这些函数用于在特定分组或全表中为行分配唯一的序号。 - RANK():如果两行在同一组中的值相同,它们将被赋予相同的排名,然后跳过下一个排名。 - DENSE_RANK():与RANK...

    oracle分组排序统计高级用法

    其中`GROUP BY`、`ORDER BY`、`OVER`子句以及`ROW_NUMBER()`、`RANK()`、`DENSE_RANK()`等分析函数都是非常有用的工具。在实际应用中,根据具体的需求选择合适的工具和技术组合可以大大提高数据处理的效率和灵活性。...

    hive开窗函数详细介绍

    本文将详细探讨Hive的开窗函数,包括ROW_NUMBER、RANK、DENSE_RANK以及分析窗口函数SUM、AVG、MIN和MAX的用法。 一、窗口函数 1. ROW_NUMBER() ROW_NUMBER()函数为每个分区内的记录分配一个唯一的连续编号,根据...

    SQL Server 2005 提供了4个行号排序函数

    本文将详细介绍这四个行号排序函数:`ROW_NUMBER()`、`RANK()`、`DENSE_RANK()` 和 `NTILE()` 的用法和应用场景。 #### 二、ROW_NUMBER() `ROW_NUMBER()` 函数为分区中的每一行分配一个唯一的数字。该函数对于实现...

    (开发人员应当读的文章)Bob Lyle 谈 DB2 中的 OLAP 函数

    DENSE_RANK() OVER (PARTITION BY dept ORDER BY salary DESC NULLS LAST) AS dense_rank, ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESC NULLS LAST) AS row_number FROM emptab; ``` 这里使用`...

    oracle统计函数.pdf

    本文档主要介绍了Oracle数据库中的几种统计函数,包括row_number(), rank()和dense_rank(),以及它们的使用方法和应用场景。 1. row_number()函数:这是一个窗口函数,用于为每行生成一个唯一的序号。其基本语法为...

Global site tag (gtag.js) - Google Analytics