zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    java如何将char类型的数字转换成int型的数字,而不是Ascii
    java 二分查找的注意事项
    IntelliJ IDEA 下的svn配置及使用的非常详细的图文总结
    java中Math的常用方法整理
    判断字符串是否可由重复子字符串组成
    P3558 [POI2013]BAJ-Bytecomputer
    BZOJ 3329. Xorequ
    Codeforces 1221F. Choose a Square
    Codeforces 1221E. Game With String
    Codeforces 1221D. Make The Fence Great Again
  • 原文地址:https://www.cnblogs.com/volcao/p/13763908.html
Copyright © 2011-2022 走看看