rank()over 函數的使用

1. over()是分析函數,能夠和rank()函數配合使用,也能夠和其餘函數配合使用。
取每一個學科排名前三的分數,sql語句以下:
select * from (select rank() over(partition by subject order by mark desc) rk,S.* from S) T 
where T.rk<=3;

排列(rank())函數。這些排列函數提供了定義一個集合(使用 PARTITION 子句),而後根據某種排序方式對這個集合內的元素進行排列的能力,下面以scott用戶的emp表爲例來講明rank over partition如何使用sql

1)查詢員工薪水並連續求和oracle

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.34it

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.31io

2)以下:table

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 empast

結果以下:class

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

注:

rank()涵數主要用於排序,並給出序號

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 ( [query_partition_clause] 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,也就是最高分。這樣就完成了需求。

相關文章
相關標籤/搜索