3. IDごとのValの順位(Rank)を求める
次は、IDごとValの順位(Rank)
を求めるSQLについてです。まずは、テーブルのデータと、出力結果を考えます。
ID | Seq | Val |
AA | 1 | 100 |
AA | 2 | 100 |
AA | 3 | 500 |
AA | 4 | 200 |
AA | 5 | 200 |
AA | 6 | 50 |
BB | 1 | 200 |
BB | 2 | 400 |
BB | 3 | 800 |
BB | 4 | 900 |
CC | 1 | 100 |
CC | 2 | 800 |
CC | 3 | 700 |
DD | 1 | 400 |
EE | 1 | 50 |
FF | 1 | 10 |
FF | 3 | 20 |
FF | 5 | 40 |
FF | 6 | 80 |
IDごとValの順位(Rank)
を求めます。同点があったら、その分だけ順位に歯抜けが発生します。
言いかえれば、Oracleの下記の分析関数を使ったSQLと同じ結果を取得します。
select ID,Seq,Val, Rank() over(partition by ID order by Val desc) as Rn from IDTable order by ID,Rn,Seq;
ID | Seq | Val | Rn |
AA | 3 | 500 | 1 |
AA | 4 | 200 | 2 |
AA | 5 | 200 | 2 |
AA | 1 | 100 | 4 |
AA | 2 | 100 | 4 |
AA | 6 | 50 | 6 |
BB | 4 | 900 | 1 |
BB | 3 | 800 | 2 |
BB | 2 | 400 | 3 |
BB | 1 | 200 | 4 |
CC | 2 | 800 | 1 |
CC | 3 | 700 | 2 |
CC | 1 | 100 | 3 |
DD | 1 | 400 | 1 |
EE | 1 | 50 | 1 |
FF | 6 | 80 | 1 |
FF | 5 | 40 | 2 |
FF | 3 | 20 | 3 |
FF | 1 | 10 | 4 |
順位は、自分より高得点の人の数に1を加算したものだと考えて、下記が答えとなります。
select ID,Seq,Val, (select count(*)+1 from IDTable b where b.ID = a.ID and b.Val > a.Val) as Rn from IDTable a order by ID,Rn,Seq;
前問と似た考え方を使っていて、相関サブクエリでwhere b.ID = a.ID
を指定して、外側のselect
文の結果と同じIDを条件とし、さらに、Valが自分より大きいことを条件として、count
関数で件数を求めて、1を加算してます。結果としてIDごとValの順位(Rank)
が求まります。
SQLのイメージは下記となります。