在進行數據分析時,我們常常需要為查詢結果集中的每條記錄生成一個唯一的序號或行號。例如:
- 為每位員工按照入職時間排序并編號;
- 按照訂單金額對訂單進行排序,并給每個訂單分配一個順序編號;
- 在分組數據內為每條記錄編號。
這時候就需要使用 SQL 中非常有用的窗口函數 —— ROW_NUMBER()
!
它可以幫助我們輕松地為查詢結果集中的每一行分配一個獨一無二的行號,特別適合處理涉及排序和分組的數據分析任務。
?什么是 ROW_NUMBER()?
ROW_NUMBER()
是 SQL 中用于為分區或整個結果集中的行生成唯一行號的窗口函數。它會根據指定的排序規則為每條記錄分配一個連續的行號,即使存在相同的值也不會導致行號跳過。
你可以把它理解為:“按照某個標準給每條記錄打上獨一無二的行號標簽”。
?基本語法
SELECT column1, column2, ...,
ROW_NUMBER() OVER ([PARTITION BY partition_column]ORDER BY sort_column [ASC|DESC], ...
) AS row_num
FROM table_name;
PARTITION BY
(可選):定義如何將數據劃分為不同的分區(類似于?GROUP BY
),每個分區獨立進行編號。ORDER BY
:指定用于決定行號順序的列及其方向(升序或降序)。
?示例講解
假設我們有一個 employees
表,記錄了員工的信息:
employee_id | name | hire_date |
---|---|---|
1 | 張三 | 2020-06-01 |
2 | 李四 | 2019-05-23 |
3 | 王五 | 2021-07-15 |
4 | 趙六 | 2020-08-10 |
5 | 孫七 | 2018-03-12 |
?示例1:按入職日期為所有員工編號
SELECT name, hire_date,
ROW_NUMBER() OVER (ORDER BY hire_date ASC) AS row_num
FROM employees;
結果:
name | hire_date | row_num |
---|---|---|
孫七 | 2018-03-12 | 1 |
李四 | 2019-05-23 | 2 |
張三 | 2020-06-01 | 3 |
趙六 | 2020-08-10 | 4 |
王五 | 2021-07-15 | 5 |
?注意:這里我們按入職日期進行了升序排列,并為每位員工分配了一個連續的行號。
?示例2:按部門對員工進行編號(使用 PARTITION BY)
假設我們增加了一個 department
列來表示員工所屬的部門:
employee_id | name | department | hire_date |
---|---|---|---|
1 | 張三 | 銷售部 | 2020-06-01 |
2 | 李四 | 銷售部 | 2019-05-23 |
3 | 王五 | 技術部 | 2021-07-15 |
4 | 趙六 | 技術部 | 2020-08-10 |
5 | 孫七 | 銷售部 | 2018-03-12 |
SELECT name, department, hire_date,
ROW_NUMBER() OVER (PARTITION BY department ORDER BY hire_date ASC) AS row_num
FROM employees;
結果:
name | department | hire_date | row_num |
---|---|---|---|
孫七 | 銷售部 | 2018-03-12 | 1 |
李四 | 銷售部 | 2019-05-23 | 2 |
張三 | 銷售部 | 2020-06-01 | 3 |
王五 | 技術部 | 2021-07-15 | 1 |
趙六 | 技術部 | 2020-08-10 | 2 |
?這里我們按部門進行了劃分,然后在每個部門內部根據入職日期進行編號。
?示例3:結合其他聚合函數使用
有時候你可能還需要同時計算一些匯總信息,比如總人數、平均入職年限等。下面的例子展示了如何同時顯示編號和部門總人數:
SELECT name, department, hire_date,
ROW_NUMBER() OVER (PARTITION BY department ORDER BY hire_date ASC) AS row_num,
COUNT(*) OVER (PARTITION BY department) AS total_employees_in_dept
FROM employees;
結果:
name | department | hire_date | row_num | total_employees_in_dept |
---|---|---|---|---|
孫七 | 銷售部 | 2018-03-12 | 1 | 3 |
李四 | 銷售部 | 2019-05-23 | 2 | 3 |
張三 | 銷售部 | 2020-06-01 | 3 | 3 |
王五 | 技術部 | 2021-07-15 | 1 | 2 |
趙六 | 技術部 | 2020-08-10 | 2 | 2 |
注意
對比項 | 使用建議 |
---|---|
唯一行號 | 即使有相同的排序值,ROW_NUMBER() ?也會為每條記錄分配一個唯一的行號 |
不同的排名函數 | -?RANK() :允許并列排名,但會導致行號跳躍 |
-?DENSE_RANK() :與?RANK() ?類似,但不會跳過行號 | |
性能優化 | 盡量減少?PARTITION BY ?的范圍以提高性能 |
數據一致性 | 在執行復雜的編號操作時,確保數據的一致性和準確性 |
?總結對比表
場景 | SQL 示例 |
---|---|
按單一條件編號 | SELECT ..., ROW_NUMBER() OVER (ORDER BY hire_date ASC) AS row_num FROM employees; |
按部門內條件編號 | SELECT ..., ROW_NUMBER() OVER (PARTITION BY department ORDER BY hire_date ASC) AS row_num FROM employees; |
結合其他聚合函數使用 | SELECT ..., ROW_NUMBER() OVER (PARTITION BY department ORDER BY hire_date ASC) AS row_num, COUNT(*) OVER (PARTITION BY department) AS total_employees_in_dept FROM employees; |
希望這篇簡短的指南幫助你快速了解了 ROW_NUMBER()
窗口函數的強大功能。