ROW_NUMBER() 函數 (SQL ROW_NUMBER() Function)

ROW_NUMBER() 是一種窗口函數 (Window Function),它會為查詢結果集中的每一列指派一個連續的整數編號,編號從 1 開始。

ROW_NUMBER 語法

ROW_NUMBER() OVER (
    [PARTITION BY column_name(s)]
    ORDER BY column_name(s)
)
  • PARTITION BY: 選用,用來將結果分組,每組的編號會重新從 1 開始
  • ORDER BY: 必填,決定編號的排列依據

ROW_NUMBER 基本用法 (Example)

假設我們有一個 employees 資料表:

E_IdNameDeptSalary
1張一業務50000
2王二研發60000
3李三業務55000
4趙四研發70000

依薪資高低為每列編號:

SELECT 
    Name,
    Salary,
    ROW_NUMBER() OVER (ORDER BY Salary DESC) AS RowNum
FROM employees;

查詢結果:

NameSalaryRowNum
趙四700001
王二600002
李三550003
張一500004

PARTITION BY 分組編號 (Example)

使用 PARTITION BY 可以在每個部門內分別編號:

SELECT 
    Name,
    Dept,
    Salary,
    ROW_NUMBER() OVER (PARTITION BY Dept ORDER BY Salary DESC) AS DeptRank
FROM employees;

查詢結果:

NameDeptSalaryDeptRank
李三業務550001
張一業務500002
趙四研發700001
王二研發600002

實務應用:取各部門薪資最高的員工

SELECT Name, Dept, Salary
FROM (
    SELECT 
        Name, Dept, Salary,
        ROW_NUMBER() OVER (PARTITION BY Dept ORDER BY Salary DESC) AS rn
    FROM employees
) AS ranked
WHERE rn = 1;

查詢結果:

NameDeptSalary
李三業務55000
趙四研發70000

實務應用:分頁查詢

ROW_NUMBER() 常用於實作分頁功能,例如取第 11 到 20 筆資料:

SELECT *
FROM (
    SELECT 
        *,
        ROW_NUMBER() OVER (ORDER BY E_Id) AS rn
    FROM employees
) AS numbered
WHERE rn BETWEEN 11 AND 20;

ROW_NUMBER 與 RANK、DENSE_RANK 的差異

當排序欄位有相同值時,三者的編號方式不同:

  • ROW_NUMBER(): 即使值相同也會給不同編號 (1, 2, 3, 4...)
  • RANK(): 相同值給相同編號,之後跳號 (1, 1, 3, 4...)
  • DENSE_RANK(): 相同值給相同編號,之後不跳號 (1, 1, 2, 3...)