【ORACLE】RANK関数


OracleのRANK関数-いわゆる「順位」をつけるための関数-の使い方の個人的なメモ


基本的な使い方はSELECTの項目内に以下のように記述する↓

rank() over(order by COLUMN_NAME [ASC|DESC] )  

という感じ。
・何か指定できるみたいだが、この使い方だと同値は同順になり、次の値から重複した分を加味した順位になっていく。
・検索結果は、over()内に指定した順序で並び替えられるので、通常順序付けにあたって最後部につけるORDER BYは不要。



 


 

例でいうと。

■TEST_RANK

IDVALUE

01 100
02 120
03 100
04 100
05 50


これに対して

select  
   rank() over(order by value desc) as RANKING  
   ,id  
   ,value  
from TEST_RANK  

というSQLを投げると

RANKINGIDVALUE

1 02 120
2 01 100
2 03 100
2 04 100
5 05 50

になる。
・並びはover内の指定でVALUEの降順(desc)になる(VALUEが大きい方が順位が小さい。)
・ID=02はVALUE=120で降順1位なのでRANKING=1
・ID=01、03、04はVALUE=100なので降順2位、かつ同順でRANKING=2
・ID=05はVALUE=50なので降順3位でRNAKING=3
という結果になる。

ちなみにID=01、03、04はVALUEでは同順だけどIDが違う。
RANK関数の並び順にIDを加えると順位も変わる。

select  
   rank() over(order by value desc,id) as RANKING  
   ,id  
   ,value  
from TEST_RANK  

↑のようにすると、上記の結果はIDまで含めた順位づけをされるため

RANKINGIDVALUE

1 02 120
2 01 100
3 03 100
4 04 100
5 05 50

という感じになって重複のない順位に変わってくる。

逆に言うとIDの並びに関して指定がない「 rank() over(order by value desc)」だと、
ID=01、03、04はSELECT結果のRANK値こそ一緒だがどういう順番で返ってくるかわからない(ソート順が指定されてないから返却位置は保障されない)。



ちなみにrankと普通のoreder byを混在させると、返却結果としては少なくとも同一SELECT内では普通のorder byのほうが優先されるらしい。
というか要するに「順位付けした後にorder byで並び替える」という動きになるのだと思う。

select  
   rank() over(order by value desc) as RANKING  
   ,id  
   ,value  
from TEST_RANK  
order by   id  

↑のようにすると、RANKは付くのだが返却結果の並びがRANKING順にならず

RANKINGIDVALUE

2 01 100
1 02 120
2 03 100
2 04 100
5 05 50

↑のようになる。
要するにID=01のRANKING値に関わらず、ID=01が一番上に来てしまう。
RANKING(RNAK関数による順序付け)は正しく出来ているから、
返却されたレコードの結果の見方(基準)がどうなるかに過ぎない。
「順位はあくまで補足の追加情報で、基本的には仕様で取り決めた順序に従いソート」というケースで必要になりそうだが、
その場でRANKまで付与するよりは事前にバッチ処理かなんかで作っておいた方がいい気もする。