前回のレクチャーでウィンドウ関数がなんで必要なのか分かったよね。今回は具体的な関数とその結果を見てみよう。構文の細かい話は次のレクチャーでやるよ。
ROW_NUMBER() 関数
ROW_NUMBER() 関数はウィンドウ内で各行にユニークな番号を返すよ。これは ORDER BY で決めた順番で単純に行をナンバリングするだけ。
構文:
ROW_NUMBER() OVER ([PARTITION BY column] ORDER BY column)
ここで:
PARTITION BY column(オプション): データをグループに分ける。省略すると全体でナンバリングされるよ。ORDER BY column: ナンバリングの順番を決める。
例:テーブルの行をナンバリングする
students テーブルを使って、学生とそのスコアの情報が入ってるとするよ。
SELECT * FROM students;
| id | name | score |
|---|---|---|
| 1 | Eva Lang | 95 |
| 2 | Maria Chi | 87 |
| 3 | Alex Lin | 78 |
| 4 | Anna Song | 95 |
| 5 | Otto Mart | 87 |
じゃあ、スコア(score)の降順で行をナンバリングしてみよう:
SELECT
name,
score,
ROW_NUMBER() OVER (ORDER BY score DESC) AS row_num
FROM students;
結果:
| name | score | row_num |
|---|---|---|
| Eva Lang | 95 | 1 |
| Anna Song | 95 | 2 |
| Maria Chi | 87 | 3 |
| Otto Mart | 87 | 4 |
| Alex Lin | 78 | 5 |
各行がスコアの降順でユニークな番号をもらってるね。
これはシンプルだけど超便利な操作で、クエリの結果に行番号を追加できる。クラシックな SELECT だけじゃウィンドウ関数なしでこれはできないよ。
RANK() 関数
RANK() 関数は ROW_NUMBER() にすごく似てるけど、同じ値を考慮するってとこが違う。同じ値が並んでたら同じランクになるし、次のランクは飛ばされる。
構文:
RANK() OVER ([PARTITION BY column] ORDER BY column)
例:学生をスコアでランク付け
同じデータで RANK() を使ってみよう:
SELECT
name,
score,
RANK() OVER (ORDER BY score DESC) AS rank
FROM students;
結果:
| name | score | rank |
|---|---|---|
| Eva Lang | 95 | 1 |
| Anna Song | 95 | 1 |
| Maria Chi | 87 | 3 |
| Otto Mart | 87 | 3 |
| Alex Lin | 78 | 5 |
ここでは同じ値(95 と 87)の行が同じランクになってて、次のランクが飛ばされてるね。
DENSE_RANK() 関数
DENSE_RANK() は RANK() に似てるけど、ランクの値が飛ばされないのがポイント。同じ値があっても、次のランクは前のランク+1になる。
構文:
DENSE_RANK() OVER ([PARTITION BY column] ORDER BY column)
例:密なランク付け
同じデータで DENSE_RANK() を使ってみよう:
SELECT
name,
score,
DENSE_RANK() OVER (ORDER BY score DESC) AS dense_rank
FROM students;
結果:
| name | score | dense_rank |
|---|---|---|
| Eva Lang | 95 | 1 |
| Anna Song | 95 | 1 |
| Maria Chi | 87 | 2 |
| Otto Mart | 87 | 2 |
| Alex Lin | 78 | 3 |
ここでは RANK() と違って、ランクの値が飛ばされずに連続してるよ。
NTILE() 関数
NTILE() 関数は行を均等なグループ(分位数)に分けて、それぞれの行にグループ番号をつけるよ。
構文:
NTILE(n) OVER ([PARTITION BY column] ORDER BY column)
n: データを分けるグループ数。
例:学生を3グループに分ける
スコアの降順で学生を3つのグループに分けてみよう:
SELECT
name,
score,
NTILE(3) OVER (ORDER BY score DESC) AS group_num
FROM students;
結果:
| name | score | group_num |
|---|---|---|
| Eva Lang | 95 | 1 |
| Anna Song | 95 | 1 |
| Maria Chi | 87 | 2 |
| Otto Mart | 87 | 2 |
| Alex Lin | 78 | 3 |
注意:行数がきっちり均等に分けられない場合、余った行は最初のグループから順に入るよ。この例だと最初の2グループが2行ずつ、最後のグループが1行になってる。
どの関数をいつ使う?
ROW_NUMBER(): ソート順でユニークな行番号が欲しいとき。RANK(): 同じ値を考慮してランク付けしたい、ランクの値を飛ばしてもOKなとき。DENSE_RANK(): 同じ値を考慮してランク付けしたい、ランクの値を飛ばしたくないとき。NTILE(): 行を均等なグループに分けたいとき。
これらの関数を使えば、データ分析の幅がめっちゃ広がるよ。順番の計算やグループ分けが柔軟にできる場面でガンガン使ってみて!
GO TO FULL VERSION