參考 1:Microsoft 中的 SQL Server 文檔(分析函數、排名行數、聚合函數、OVER窗口函數)
參考 2:SQL Server 分析函數和排名函數 博主:悅光陰
- 分析函數基於分組,計算分組內數據的聚合值,經常會和窗口函數OVER()一起使用,使用分析函數可以很方便地計算同比和環比,獲得中位數,獲得分組的最大值和最小值。
- 分析函數和聚合函數不同,不需要GROUP BY子句,對SELECT子句的結果集,通過OVER()子句分組;
一,分析函數
- 分析函數通常和 OVER() 函數搭配使用,SQL Server 中共有4類分析函數。
- 注意:distinct 子句的執行順序是在分析函數之后。
1,分布函數:CUME_DIST、PERCENT_RANK
- 功能:計算某個值在某個值組內的累積分布;換言之,
CUME_DIST
計算某指定值在一組值中的相對位置。
- CUME_DIST 計算的邏輯是:小於等於當前值的行數 / 分組內總行數;
- PERCENT_RANK 計算的邏輯是:(分組內當前行的 RANK 值-1)/ (分組內總行數-1),排名值是 RANK() 函數排序的結果值;
-
示例:
-
select Department ,LastName ,Rate ,cume_dist() over(partition by Department order by Rate) as CumeDist ,percent_rank() over(partition by Department order by Rate) as PtcRank ,rank() over(partition by Department order by Rate asc) as rank_number ,count(0) over(partition by Department) as count_in_group from #data order by DepartMent ,Rate desc
-
2,分布函數:PERCENTILE_CONT、PERCENTILE_DISC
-
功能:
- 都是為了計算百分位的數值,比如計算在某個百分位時某個欄位的數值是多少;
- 如,20% —— 一組數據中,分布位置在 20% 處的數值、50% —— 分布位置在 50% 處的數值,也就是中位數;
-
語法:
-
PERCENTILE_CONT ( numeric_literal ) WITHIN GROUP ( ORDER BY order_by_expression [ ASC | DESC ] ) OVER ( [ <partition_by_clause> ] ) PERCENTILE_DISC ( numeric_literal ) WITHIN GROUP ( ORDER BY order_by_expression [ ASC | DESC ] ) OVER ( [ <partition_by_clause> ] )
-
-
區別:
- 這兩個函數的區別是前者是連續型,后者是離散型。
- CONT代表continuous,連續值,DISC代表discrete,離散值。
- PERCENTILE_CONT是連續型,意味它考慮的是區間,所以值是絕對的中間值;
- PERCENTILE_DISC是離散型,所以它更多考慮向上或者向下取舍,而不會考慮區間;
-
示例:
-
select Department ,LastName ,Rate ,PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY Rate) OVER (PARTITION BY Department) AS MedianCont ,PERCENTILE_DISC(0.5) WITHIN GROUP (ORDER BY Rate) OVER (PARTITION BY Department) AS MedianDisc ,row_number() over(partition by Department order by Rate) as rn from #data order by DepartMent ,Rate asc
-
3,偏移函數:LAG、LEAD
-
功能:
- 對某列數據進行偏移;
-
區別:
- LAG:向下偏移 —— 如果偏移 n 行數據(即 offset=n),舊列中的第一行數據,在新列中為第 n+1 行數據;
- LEAD:向上偏移 —— 如果偏移 n 行數據(即 offset=n),舊列中的第一行數據,在新列中為第 n+1 行數據,
-
語法:
-
LAG (scalar_expression [,offset] [,default]) OVER ( [ partition_by_clause ] order_by_clause ) LEAD ( scalar_expression [ ,offset ] , [ default ] ) OVER ( [ partition_by_clause ] order_by_clause )
- sclar_expression
- 偏移的對象,即 舊列;
- offset
- 偏移量;
- 如,offset=n,表示偏移了 n 行數據;
- 默認值是1,必須是正整數;
- 偏移量;
- default
- 偏移后的偏移區的取值;
- 如, LAG 偏移了 n 行,則新列中的前 n 行的數據即為 default;
- 如果未指定默認值,則返回NULL;
- default 可以是列,子查詢或其他表達式,但數據類型必須跟 sclar_expression 類型兼容;
- 偏移后的偏移區的取值;
-
-
示例:
- 結果日期,這兩個函數特別適合用於計算同比和環比;
-
select DepartMent ,LastName ,Rate ,lag(Rate,1,0) over(partition by Department order by LastName) as LastRate ,lead(Rate,1,0) over(partition by Department order by LastName) as NextRate from #data order by Department ,LastName
-
理解:
- scalar_expression = Rate:對 Rate 列的數據進行偏移;
- offset=1:偏移量設置為 1;(即偏移一行數據)
- default=0:偏移區的數據設置為 0;
- 如新列 LastRate 的第一個分組的第 1 行數據;(向下偏移 1 行數據)
- 如新列 NextRate 的第一個分組的第 5 行數據;(向上偏移 1 行數據)
4,偏移函數:FIRST_VALUE、LAST_VALUE、NTH_VALUE
-
功能:
- FIRST_VALUE:返回 scalar_expression 列中,分組中的第一行的數據;
- LAST_VALUE:返回 scalar_expression 列中,分組中的最后一行的數據;
- NTH_VALUE:返回 scalar_expression 列中,每個分組的偏移量;(即 offset 值)
-
語法:
-
LAST_VALUE ( [scalar_expression ) OVER ( [ partition_by_clause ] order_by_clause rows_range_clause ) FIRST_VALUE ( [scalar_expression ] ) OVER ( [ partition_by_clause ] order_by_clause [ rows_range_clause ] )
- scalar_expression —— 目標列:如果對該列進行了分組和排序,則返回該列中的每個分組中的第一行 / 最后一行的數據;
-
-
示例:
-
USE AdventureWorks2012; GO SELECT Name, ListPrice, FIRST_VALUE(Name) OVER (ORDER BY ListPrice ASC) AS LeastExpensive FROM Production.Product WHERE ProductSubcategoryID = 37;
- 理解:返回結果集中 Name 列中的第一行數據;
-
二,排名函數
- TSQL共有4個排名函數:RANK、NTILE、DENSE_RANK、ROW_NUMBER,和 OVER() 函數搭配使用,按照特定的順序排名。
1,ROW_NUMBER
- 這個函數賦予唯一的連續位次;
- 如,有 3 條排在第1位時,排序為:1,2,3,4······
-
ROW_NUMBER ( ) OVER ( [ PARTITION_BY_clause ] order_by_clause )
-
分組內序列的最大值就是該分組內的行的數目;
2,RANK
- 功能:在計算排序時,若存在相同位次,會跳過之后的位次;
- 如,有3條排在第1位時,排序為:1,1,1,4······
-
RANK ( ) OVER ( [ partition_by_clause ] order_by_clause )
3,DENSE_RANK
- 功能: 在計算排序時,若存在相同位次,不會跳過之后的位次。
- 如,有3條排在第1位時,排序為:1,1,1,2······
-
DENSE_RANK ( ) OVER ( [ <partition_by_clause> ] < order_by_clause > )
4,NTILE
- 功能:對每個分組的所有數據進行分塊標記,每個標記就是該行數據所在第幾個數據塊;
- 如,integer_expression=3:把一個分組的數據分成 3 分;(則每個數據塊的行數 = 分組數據總行數 / 3,如果不能整除,最后一個數據塊的數據記錄最少)
-
語法:
-
NTILE (integer_expression) OVER ( [ <partition_by_clause> ] < order_by_clause > )
-
-
示例
-
-
select Department, LastName, Rate, row_number() over(order by Rate) as [row number], rank() over(order by rate) as rate_rank, dense_rank() over(order by rate) as rate_dense_rank, ntile(4) over(order by rate) as quartile_by_rate from test_data
-
三、聚合函數 配合 OVER 函數
- 一般配合 OVER 函數使用的聚合函數:SUM、COUNT、AVG、MAX、MIN;
-
功能:
- SUM、AVG:返回累積計算結果;
- 如,第 n 行的數據,是從前 n 行數據中計算得到;
- COUNT、MAX、MIN:返回分組中的行數、最大值、最小值,一個分組返回一行數;
- SUM、AVG:返回累積計算結果;
-
語法:
- 對一列的分組進行計算
-
<窗口函數> OVER([pattition by col_a] ORDER BY col_b)
-
- 不分組,直接對某列進行計算
-
<窗口函數(col_a)> OVER(ORDER BY col_b)
-
- 對一列的分組進行計算
-
示例:
-
SUM:累積求和
- 第 n 行數據為前 n 行數據的總和;
-
select product_id, product_name, sale_price, sum(sale_price) over (order by product_id) as current_sum from Product;
-
AVG:累積求平均
- 第 n 行的數據為前 n 行數據的平均數;
-
select product_id, product_name, sale_price, avg(sale_price) over (order by product_id) as current_sum from Product;
-
AVG:移動平均(一)
- 計算前 n 行 + 改行數據的平均值;
- 如,n=2:計算相鄰 3 行數據,即 (前 2 行 + 本身行數據) / 3;
- 如,當 n=2 時,第 10 行的數據 = (第8行 + 第9行 + 第10行) / 3
- 如,n=2:計算相鄰 3 行數據,即 (前 2 行 + 本身行數據) / 3;
-
語法:
-
<聚合函數> OVER([PARTITION BY col_a] ORDER BY col_b ROWS n PRECEDING)
-
-
示例:
-
SELECT product_id, product_name, sale_price, AVG (sale_price) OVER (ORDER BY product_id ROWS 2 PRECEDING) AS moving_avg FROM Product;
- n = 2:計算前兩行+本行數據的平均值;
- 第 3 行:1833 = (1000+500+4000) / 3
- 第 4 行:2500 = (500+4000+3000) / 3
- 第 5 行:4600 = (4000+3000+6800) / 3
-
- 計算前 n 行 + 改行數據的平均值;
-
AVG:移動平均(二)
- 功能:(計算上一行 + 下一行 + 該行) / 3;
-
語法及示例:
-
SELECT product_id, product_name, sale_price, AVG(sale_price) OVER (ORDER BY product_id ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS moving_avg
--使用between規划范圍,語句意思為rows 1 preceding 到 rows 1 following FROM Product;- 4600 = (4000+3000+6800) / 3
-