SQL SERVER的PARTITION BY關鍵字說明介紹
- PARTITION BY關鍵字介紹
- 具體使用場景
- 排名計算
- 累計求和
- 分組求最值
- 分組內百分比計算
- 分組內移動平均計算
- 分組內數據分布統計
- 分組內數據偏移計算
- 總結
PARTITION BY關鍵字介紹
在SQL SERVER中,關鍵字PARTITION BY主要用于窗口函數中,它能將查詢結果集按照指定的列或表達式劃分成多個分區(組),然后窗口函數會在每個分區內獨立地進行計算
通俗來講就是:它可以把結果集拆分成多個邏輯組,窗口函數會基于這些組來執行操作,而不是對整個結果集進行統一處理。這樣就能在每個分區內完成特定的計算,比如排名、求和、求平均值等
具體使用場景
假設存在一個 Sales 表,包含 Region(地區)、Salesperson(銷售人員)和 SalesAmount(銷售金額)列
排名計算
要在每個地區內為銷售人員按銷售金額進行排名
SELECT Region,Salesperson,SalesAmount,RANK() OVER (PARTITION BY Region ORDER BY SalesAmount DESC) AS SalesRank
FROM Sales;
--PARTITION BY Region:將結果集按照 Region 列的值進行分區,每個地區形成一個獨立的組。
--ORDER BY SalesAmount DESC:在每個地區分區內,按照 SalesAmount 列的值降序排序。
--RANK():為每個分區內的銷售人員計算排名。
累計求和
若要計算每個地區內銷售人員的累計銷售金額,可以使用 SUM() 窗口函數
SELECT Region,Salesperson,SalesAmount,SUM(SalesAmount) OVER (PARTITION BY Region ORDER BY Salesperson) AS CumulativeSales
FROM Sales;--PARTITION BY Region:按 Region 列的值對結果集進行分區。--ORDER BY Salesperson:在每個地區分區內,按照 Salesperson 列的值進行排序。--SUM(SalesAmount):在每個分區內計算累計銷售金額
分組求最值
在每個分組中找出最大值或最小值,例如有一個 Products 表,包含 Category(產品類別)、ProductName(產品名稱)和 Price(價格)列,要找出每個類別中價格最高的產品信息
SELECT Category,ProductName,Price
FROM (SELECT Category,ProductName,Price,ROW_NUMBER() OVER (PARTITION BY Category ORDER BY Price DESC) AS rnFROM Products
) subquery
WHERE rn = 1;--這里先使用 PARTITION BY Category 將產品按類別分組,在每個類別分組內按照價格降序排列并為每行分配行號 rn,最后篩選出 rn = 1 的記錄,也就是每個類別中價格最高的產品
分組內百分比計算
計算每個分組內某一數值占該組總和的百分比。假設有一個 Orders 表,包含 Region(地區)和 OrderAmount(訂單金額)列,要計算每個地區的訂單金額占該地區訂單總金額的百分比
SELECT Region,OrderAmount,OrderAmount * 1.0 / SUM(OrderAmount) OVER (PARTITION BY Region) AS Percentage
FROM Orders;--PARTITION BY Region 把訂單按地區分組,SUM(OrderAmount) OVER (PARTITION BY Region) 計算每個地區的訂單總金額,然后用當前訂單金額除以該地區總金額得到百分比
分組內移動平均計算
在分組內計算移動平均值,常用于分析數據的趨勢。例如有一個 StockPrices 表,包含 StockSymbol(股票代碼)、TradeDate(交易日期)和 ClosingPrice(收盤價)列,要計算每個股票最近 3 天的移動平均收盤價。
SELECT StockSymbol,TradeDate,ClosingPrice,AVG(ClosingPrice) OVER (PARTITION BY StockSymbol ORDER BY TradeDate ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS MovingAverage
FROM StockPrices;-- PARTITION BY StockSymbol 按股票代碼分組,ORDER BY TradeDate 按交易日期排序,ROWS BETWEEN 2 PRECEDING AND CURRENT ROW 表示在當前行及前兩行的范圍內計算平均值,這樣就得到了每個股票最近 3 天的移動平均收盤價
分組內數據分布統計
統計每個分組內不同數據區間的分布情況。比如有一個 Students 表,包含 Class(班級)和 Score(分數)列,要統計每個班級中不同分數段(如 0 - 59、60 - 79、80 - 100)的學生數量
SELECT Class,CASE WHEN Score BETWEEN 0 AND 59 THEN '0 - 59'WHEN Score BETWEEN 60 AND 79 THEN '60 - 79'WHEN Score BETWEEN 80 AND 100 THEN '80 - 100'END AS ScoreRange,COUNT(*) OVER (PARTITION BY Class, CASE WHEN Score BETWEEN 0 AND 59 THEN '0 - 59'WHEN Score BETWEEN 60 AND 79 THEN '60 - 79'WHEN Score BETWEEN 80 AND 100 THEN '80 - 100'END) AS StudentCount
FROM Students;--先通過 CASE 語句將分數劃分成不同區間,然后使用 PARTITION BY Class, ScoreRange 按班級和分數段分組,COUNT(*) 統計每個分組內的學生數量
分組內數據偏移計算
計算每個分組內當前行與前一行或后一行數據的差值等偏移量。例如有一個 SalesData 表,包含 Product(產品)、Month(月份)和 SalesVolume(銷售數量)列,要計算每個產品每月銷售數量相較于前一個月的增長數量
SELECT Product,Month,SalesVolume,SalesVolume - LAG(SalesVolume) OVER (PARTITION BY Product ORDER BY Month) AS Growth
FROM SalesData;--PARTITION BY Product 按產品分組,ORDER BY Month 按月份排序,LAG(SalesVolume) 函數獲取當前行前一行的銷售數量,用當前行銷售數量減去前一行的銷售數量得到增長數量
總結
PARTITION BY 關鍵字讓你可以在結果集的各個分組內執行復雜的計算,而不必對整個結果集進行統一處理。這在處理分組統計、排名、累計計算等場景時非常有用,能大大提升查詢的靈活性和表達能力