萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> 資料庫綜合

SQL Server 2012 新窗口函數 FIRST_VALUE 深度解析與實戰範例

前言

SQL Server 2012 引入 ANSI SQL:2003 標準窗口函數,FIRST_VALUE、LAST_VALUE、LEAD、LAG 讓集合運算能輕鬆存取「第一筆/最後一筆/前後 N 筆」資料,徹底改寫以往需自聯結/子查詢/游標才能完成的邏輯。本文深度解析 FIRST_VALUE 語法、行為細節與實戰場景。

一、語法結構

FIRST_VALUE (scalar_expression) OVER (
    [ PARTITION BY partition_expression [ , ... ] ]
    ORDER BY order_expression [ ASC | DESC ] [ , ... ]
    [ ROWS | RANGE BETWEEN frame_start AND frame_end ]
)
  • scalar_expression:要取回的純量運算式 (欄位、函數、常數)。
  • PARTITION BY:分區,函數在各分區內獨立計算。
  • ORDER BY:決定「第一筆」的排序依據,**必填**。
  • ROWS/RANGE:框架子句,預設 RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW,對 FIRST_VALUE 通常不影響結果,但建議顯式指定 ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING 取分區絕對第一筆。

二、測試資料準備

DECLARE @TestData TABLE (
    ID INT IDENTITY(1,1),
    Department VARCHAR(20),
    LastName   VARCHAR(20),
    Rate       FLOAT
);
INSERT INTO @TestData (Department, LastName, Rate) VALUES
('Document Control','Arifin',17.7885),
('Document Control','Norred',16.8269),
('Document Control','Kharatishvili',16.8269),
('Information Services','Chai',10.25),
('Information Services','Berge',10.25),
('Information Services','Trenary',50.4808),
('Information Services','Conroy',39.6635),
('Information Services','Ajenstat',38.4615),
('Information Services','Wilson',38.4615),
('Information Services','Connelly',32.4519),
('Information Services','Meyyappan',32.4519);

三、核心行為演示

1. 無 PARTITION:全集合第一筆

SELECT *,
       FIRST_VALUE(LastName) OVER (ORDER BY ID ASC)  AS FirstByIdAsc,
       FIRST_VALUE(LastName) OVER (ORDER BY ID DESC) AS FirstByIdDesc
FROM @TestData;

結果:FirstByIdAsc 全部顯示 Arifin (ID=1);FirstByIdDesc 全部顯示 Meyyappan (ID=11)。

2. 有 PARTITION BY Department:各部門第一筆

SELECT *,
       FIRST_VALUE(LastName) OVER (PARTITION BY Department ORDER BY ID ASC) AS FirstInDept
FROM @TestData;

結果:Document Control 群組顯示 Arifin;Information Services 群組顯示 Chai。

3. ORDER BY 不同欄位:改變「第一」的定義

SELECT *,
       FIRST_VALUE(LastName) OVER (PARTITION BY Department ORDER BY Rate DESC) AS TopEarner
FROM @TestData;

結果:各部門薪資最高者 (Trenary / Kharatishvili) 顯示於每行,便於同列比較。

四、實戰場景

場景SQL 片段說明
各群組基準值對比SalesAmt - FIRST_VALUE(SalesAmt) OVER (PARTITION BY Region ORDER BY SaleDate) AS DiffFromFirst每日銷售額與該區域首日差異
客戶首單資訊攜帶FIRST_VALUE(OrderDate) OVER (PARTITION BY CustID ORDER BY OrderDate) AS FirstOrderDate每筆訂單都能看到該客戶首單日期
異常偵測基準線CASE WHEN Metric > 1.5 * FIRST_VALUE(Metric) OVER (PARTITION BY Sensor ORDER BY Ts) THEN 1 ELSE 0 END以首次讀數為基準偵測漂移

五、效能與最佳實踐

  • 索引支援:PARTITION BY + ORDER BY 欄位建立覆蓋索引,避免 Sort 運算子。
  • 框架子句:明確指定 ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING,語意清晰且避免 RANGE 對重複值的預設框架歧義。
  • 替代舊寫法:以往需 CROSS APPLY (SELECT TOP 1 ... ORDER BY ...) 或 ROW_NUMBER()=1 子查詢,FIRST_VALUE 更簡潔、優化器更易優化。

結語

FIRST_VALUE 以聲明式語法解決「取分區第一筆」經典問題,配合 PARTITION BY、ORDER BY、框架子句,靈活應對基準對比、首單屬性攜帶、異常偵測等場景。升級 SQL Server 2012+ 後,請大膽替換舊式自聯結/子查詢寫法,享受更簡潔、更高效的查詢表達。

copyright © 萬盛學電腦網 all rights reserved