SQL:分析函數、排名函數、聚合函數配合窗口函數 OVER 的用法


參考 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,離散值。
      1. PERCENTILE_CONT是連續型,意味它考慮的是區間,所以值是絕對的中間值;
      2. 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 )
    1. sclar_expression
      • 偏移的對象,即 舊列;
    2. offset
      • 偏移量;
        • 如,offset=n,表示偏移了 n 行數據;
        • 默認值是1,必須是正整數;
    3. 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
    • 理解:

      1. scalar_expression = Rate:對 Rate 列的數據進行偏移;
      2. offset=1:偏移量設置為 1;(即偏移一行數據)
      3. 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:返回分組中的行數、最大值、最小值,一個分組返回一行數;
  • 語法:

    • 對一列的分組進行計算
      • <窗口函數> 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
    • 語法:

      • <聚合函數> 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:計算前兩行+本行數據的平均值;
        1. 第 3 行:1833 = (1000+500+4000) / 3
        2. 第 4 行:2500 = (500+4000+3000) / 3
        3. 第 5 行:4600 = (4000+3000+6800) / 3

 

  • 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

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM