CREATE TABLE EMPLOYEEINFO (
CODE NUMBER(3) PRIMARY KEY,
EMPLOYEENAME VARCHAR2(15),
DEPARTMENTID NUMBER(3),
SALARY NUMBER(7,2)
);
-- 插入測試資料 (含相同薪資、NULL 值)
SELECT EMPLOYEENAME, SALARY,
RANK() OVER (ORDER BY SALARY DESC) "RANK",
DENSE_RANK() OVER (ORDER BY SALARY DESC) "DENSE_RANK",
ROW_NUMBER() OVER (ORDER BY SALARY DESC) "ROW_NUMBER"
FROM EMPLOYEEINFO;
| 函數 | 相同值處理 | 排名連續性 | 典型用途 |
|---|---|---|---|
| ROW_NUMBER | 依資料順序依序遞增,絕不重複 | 連續無間隙 | 分頁、去重取第一筆 |
| DENSE_RANK | 相同值同排名 | 連續無間隙 (1,2,2,3) | 前 N 名、並列排名 |
| RANK | 相同值同排名 | 跳號 (1,2,2,4) | 傳統排名、競賽名次 |
SELECT DEPARTMENTID, EMPLOYEENAME, SALARY,
RANK() OVER (PARTITION BY DEPARTMENTID ORDER BY SALARY DESC) "RANK",
DENSE_RANK() OVER (PARTITION BY DEPARTMENTID ORDER BY SALARY DESC) "DENSE_RANK",
ROW_NUMBER() OVER (PARTITION BY DEPARTMENTID ORDER BY SALARY DESC) "ROW_NUMBER"
FROM EMPLOYEEINFO;
各部門內獨立計算排名,互不干擾。
預設行為:ORDER BY SALARY DESC 會將 NULL 排在最前面 (視為最大值),這通常不符合業務預期。
解決方案:明確指定 NULLS LAST 或 NULLS FIRST。
SELECT EMPLOYEENAME, SALARY,
RANK() OVER (ORDER BY SALARY DESC NULLS LAST) "RANK",
DENSE_RANK() OVER (ORDER BY SALARY DESC NULLS LAST) "DENSE_RANK",
ROW_NUMBER() OVER (ORDER BY SALARY DESC NULLS LAST) "ROW_NUMBER"
FROM EMPLOYEEINFO;
加上 NULLS LAST 後,NULL 薪資員工正確排在最後。
ROW_NUMBER** 確保結果確定性。RANK (跳號) 或 DENSE_RANK (不跳號)。ORDER BY 子句**建議顯式寫出 NULLS FIRST/LAST**,避免跨版本/參數差異導致結果不一致。