上一堂課我們已經搞懂為什麼要用視窗函數。現在來看一下具體有哪些函數,以及它們的結果。語法細節我們下堂課再說。
函數 ROW_NUMBER()
ROW_NUMBER() 這個函數會在一個 window 裡,給每一列一個獨一無二的編號。就是根據 ORDER BY 排序後,單純給每一列編號啦。
語法:
ROW_NUMBER() OVER ([PARTITION BY column] ORDER BY column)
說明:
PARTITION BY column(可選):把資料分成不同 group。如果沒寫,就是整個資料集一起編號。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 |
每一列都拿到一個獨立的編號——而且是根據分數由高到低排序的。
這個操作很簡單但超實用——直接在查詢結果加上 row number。如果不用視窗函數,傳統 SELECT 是做不到的。
函數 RANK()
RANK() 跟 ROW_NUMBER() 很像,但它會考慮到一樣的值。如果有幾列分數一樣,它們會拿到一樣的 rank,下一個 rank 會跳號。
語法:
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)會拿到一樣的 rank,下一個 rank 會跳號。
函數 DENSE_RANK()
DENSE_RANK() 跟 RANK() 很像,但不會跳號。意思是如果有重複的值,下一個 rank 只會加一。
語法:
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() 不一樣,rank 只會連續增加,不會跳號。
函數 NTILE()
NTILE() 這個函數會把資料分成 n 個一樣大的 group(分位數),然後給每一列一個 group 編號。
語法:
NTILE(n) OVER ([PARTITION BY column] ORDER BY column)
n:你想要分成幾個 group。
範例:把學生分成 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 |
注意:如果資料沒辦法完全平均分組,多出來的列會先分到前面的 group。像這個例子,前兩組各有兩列,最後一組只有一列。
什麼時候該用哪個函數?
ROW_NUMBER():想要根據排序給每一列一個獨立編號時用。RANK():要排名,遇到一樣的值會跳號。DENSE_RANK():要排名,遇到一樣的值但不跳號。NTILE():想要把資料平均分組時用。
這些函數都能讓你分析資料變得超彈性。只要你需要計算順序編號或分組,都可以用它們來搞定!
GO TO FULL VERSION