前言

去年因為工作上需求,必須重新開始接觸 Stored Procedure。個人在前一間公司雖然有撰寫的經驗,但當時使用的語法相當簡單,並沒有太過於深入的彙整與研究,非常可惜。這一次透過功能開發需求,重新跟著公司資深前輩重新學習撰寫 Stored Procedure,希望藉此能將基礎打穩。序列函數 ROW_NUMBER() 正是這一次開發過程中接觸的新函式,這裡簡單紀錄並提供參考,若有任何錯誤或建議,請各位前輩不吝指教。


介紹

ROW_NUMBER 函式為顯示分割資料內的資料列的序號,每個分割資料的第一個資料序號從 1 開始。我們透過 PARTITION BY 進行資料分割,其詳細用法如下:
ROW_NUMBER ( )   
    OVER ( [ PARTITION BY expression , .... ] ORDER_BY_CLAUSE ) 

我們以 Study4 資料表為例,透過 Id 排序 並回傳資料列序號
SELECT ROW_NUMBER() OVER( ORDER BY Id DESC) AS row,
       Id,
       [Type],
       Title,
       [Description]
  FROM [dbo].[Album]



我們以 Id 進行分割資料表,來看看有什麼結果: 



你會發現 row 每個欄位都相同,為什麼呢? 因為 Id 在這個資料表沒有重複,所以每一筆資料被視為一個分割資料群,而每一群資料都會從 1 開始計算。
我們會一個 欄位 Type 進行分割 ,看看有什麼結果: 



你會發現 row 的數字不相同了,開始循序增加,相同 Type 資料會持續遞增,一個完美的資料分群。故我們多一個應用:取出每個分群的第一筆資料,就可以透過這個方法實作。下面範例為取出每種類型相簿中,Id 最大的相簿資料。
SELECT *
  FROM
    (SELECT ROW_NUMBER() OVER(PARTITION BY [TYPE] ORDER BY Id DESC) AS row,
           Id,
           [Type],
           Title,
           [Description]
      FROM [dbo].[Album]) AS RankTable
 WHERE RankTable.[row] = 1 

為什麼要特別介紹這個應用呢?我們在撰寫SP過程中,常常會使用 Group By 方法,並且遭遇 Select 欄位的問題。看過同事的 Stored Procedure 後意外發現透過 ROW_NUMBER PARTITION BY 方式能達到類似的效果,且讓程式有更多邏輯上的應用,相當實用。
 

相關文章

[Database][SQL Server] 序列函數 RANK, DENSE_RANK, NTILE 介紹與比較