1. 程式人生 > >Oracle中row_number()、rank()、dense_rank() 的區別

Oracle中row_number()、rank()、dense_rank() 的區別

des lec 分享 ast too 二級 地方 返回結果 簡化

row_number的用途非常廣泛,排序最好用它,它會為查詢出來的每一行記錄生成一個序號,依次排序且不會重復,註意使用row_number函數時必須要用over子句選擇對某一列進行排序才能生成序號。

rank函數用於返回結果集的分區內每行的排名,行的排名是相關行之前的排名數加一。簡單來說rank函數就是對查詢出來的記錄進行排名,與row_number函數不同的是,rank函數考慮到了over子句中排序字段值相同的情況,如果使用rank函數來生成序號,over子句中排序字段值相同的序號是一樣的,後面字段值不相同的序號將跳過相同的排名號排下一個,也就是相關行之前的排名數加一,可以理解為根據當前的記錄數生成序號,後面的記錄依此類推。

dense_rank函數的功能與rank函數類似,dense_rank函數在生成序號時是連續的,而rank函數生成的序號有可能不連續。dense_rank函數出現相同排名時,將不跳過相同排名號,rank值緊接上一次的rank值。在各個分組內,rank()是跳躍排序,有兩個第一名時接下來就是第三名,dense_rank()是連續排序,有兩個第一名時仍然跟著第二名。

借助實例能更直觀地理解:

假設現在有一張學生表student,學生表中有姓名、分數、課程編號。

select * from student;

技術分享圖片

現在需要按照課程對學生的成績進行排序:

--row_number() 順序排序
select name,course,row_number()
over(partition by course order by score desc) rank from student;

技術分享圖片

--rank() 跳躍排序,如果有兩個第一級別時,接下來是第三級別
select name,course,rank() over(partition by course order by score desc) rank from student;

技術分享圖片

--dense_rank() 連續排序,如果有兩個第一級別時,接下來是第二級別 
select name,course,dense_rank() over(partition by course order by score desc) rank from student;

技術分享圖片

取得每門課程的第一名:

技術分享圖片
--每門課程第一名只取一個: 
select * from (select name,course,row_number() over(partition by course order by score desc) rank from student) where rank=1;
--每門課程第一名取所有: 
select * from (select name,course,dense_rank() over(partition by course order by score desc) rank from student) where rank=1;
--每門課程第一名取所有:
select * from (select name,course,rank() over(partition by course order by score desc) rank from student) where rank=1;
技術分享圖片

  附:每門課程第一名取所有的其他方法(使用group by 而不是partition by):

技術分享圖片
select s.* from student s
  inner join(select course,max(score) as score from student group by course) c
  on s.course=c.course and s.score=c.score; 
--或者使用using關鍵字簡化連接
select * from student s
  inner join(select course,max(score) as score from student group by course) c
  using(course,score);
技術分享圖片

關於Parttion by:

  Parttion by關鍵字是Oracle中分析性函數的一部分,用於給結果集進行分區。它和聚合函數Group by不同的地方在於它只是將原始數據進行名次排列,能夠返回一個分組中的多條記錄(記錄數不變),而Group by是對原始數據進行聚合統計,一般只有一條反映統計值的結果(每組返回一條)。

  TIPS:

  使用rank over()的時候,空值是最大的,如果排序字段為null, 可能造成null字段排在最前面,影響排序結果。

  可以這樣: rank over(partition by course order by score desc nulls last)

總結:

  在使用排名函數的時候需要註意以下三點:

  1、排名函數必須有 OVER 子句。

  2、排名函數必須有包含 ORDER BY 的 OVER 子句。

  3、分組內從1開始排序。

Oracle中row_number()、rank()、dense_rank() 的區別