SQL Server 2012 引入的 FIRST_VALUE 是一個窗口函數,用於返回結果集中指定欄位的第一個值。雖然其功能類似 TOP 1,但結合 OVER() 子句後,能實現更靈活的分組與排序邏輯,是資料分析與報表開發的利器。
首先建立一個臨時表 @TestData,模擬員工薪資資料,包含部門、姓氏與時薪欄位:
DECLARE @TestData TABLE(
ID INT IDENTITY(1,1),
Department VARCHAR(20),
LastName VARCHAR(20),
Rate FLOAT
);
INSERT INTO @TestData(Department, LastName, Rate)
SELECT 'Document Control','Arifin',17.7885 UNION ALL
SELECT 'Document Control','Norred',16.8269 UNION ALL
SELECT 'Document Control','Kharatishvili',16.8269 UNION ALL
SELECT 'Information Services','Chai',10.25 UNION ALL
SELECT 'Information Services','Berge',10.25 UNION ALL
SELECT 'Information Services','Trenary',50.4808 UNION ALL
SELECT 'Information Services','Conroy',39.6635 UNION ALL
SELECT 'Information Services','Ajenstat',38.4615 UNION ALL
SELECT 'Information Services','Wilson',38.4615 UNION ALL
SELECT 'Information Services','Connelly',32.4519 UNION ALL
SELECT 'Information Services','Meyyappan',32.4519;
SELECT * FROM @TestData;

透過 OVER (ORDER BY ID) 決定「第一列」的定義。以下查詢新增欄位 FirstName,分別展示 ID 遞增與遞減時的第一筆 LastName:
-- ID 正序:第一筆為 Arifin
SELECT
*,
FIRST_VALUE(LastName) OVER (ORDER BY ID) AS FirstName_ASC
FROM @TestData;
-- ID 倒序:第一筆為 Meyyappan
SELECT
*,
FIRST_VALUE(LastName) OVER (ORDER BY ID DESC) AS FirstName_DESC
FROM @TestData;

加入 PARTITION BY Department 後,函數會在各部門內部獨立計算第一值。同樣受 ORDER BY 影響,可依薪資高低、姓名筆畫等自訂排序:
SELECT
*,
FIRST_VALUE(LastName) OVER (PARTITION BY Department ORDER BY Rate DESC) AS HighestPaid_PerDept
FROM @TestData;

對應的 LAST_VALUE 同樣存在,但預設視窗框架為 RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW,直接使用常不符預期,需顯式指定 ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING 才能正確取得分區最後一值。此處不再贅述,留待後續專文探討。