zoukankan      html  css  js  c++  java
  • sql开窗函数

    mysql8.0之前的版本是不支持开窗函数的,8.0之后才支持。

    开窗函数与聚合函数的计算方式一样,也是对行集组进行聚合计算,但是它不像普通聚合函数那样每组只返回一个值,开窗函数可以为每组返回多个值。

    假设有一个员工信息表worker,数据如下图一。如果我们要计算所有人或者每个年龄的平均工资,可通过聚合函数avg(salary) …group by...实现,如下图二和图三。我们知道聚合函数select中的列除了聚合函数,其他列必须通过group by去分组,即通过聚合函数得到的结果,只能显示聚合列、和通过聚合列聚合出来的值,无法查看这之外的其他信息。如下图三,只能查看每个年龄和对应年龄的平均工资,无法同时查看每个人的姓名和城市(当然通过子查询可以实现)。开窗函数就可以解决这个问题。

    SELECT AVG(salary) FROM worker ;SELECT age,AVG(salary) FROM worker GROUP BY(age);

       

    开窗函数的语法为:

    function(column1)

      over( [partition by column2]  -----分区元素

          [order by column3]           -----排序元素

          [row|range ......] )        -----框架元素

    partition by 和order by 可以省略也可以只出现一个。

    开窗函数主要分为两类,聚合开窗函数和排名开窗函数。

    一、聚合开窗函数

    SQL 标准允许将所有聚合函数用做开窗函数,使用over()关键字来区分这两种用法,over()关键字表示把函数当成开窗函数而不是聚合函数。

    1、over()

    如果over()括号中的参数为空,开窗函数会对结果集中的所有行进行聚合运算。

    SELECT *,AVG(salary) OVER() avg_sal FROM worker;

    2、over(partition by column)

    over()中的partition by子句用于定义行的分区来供进行聚合计算。与group by子句不同,partition by子句创建的分区独立于结果集,而且不同的开窗函数创建的分区互不影响。

    SELECT *,AVG(salary) OVER(PARTITION BY age) avg_age_sal FROM worker;SELECT *,AVG(salary) OVER(PARTITION BY age) avg_age_sal,AVG(salary) OVER(PARTITION BY city) avg_city_sal FROM worker;

      

    3、over(order by column)

    over()中的order by子句用于指定排序规则,有的开窗函数要求必须指定排序规则。使用order by子子句可以对结果集按照指定的排序规则进行排序,并且在一个指定的范围内进行聚合运算。

    order by子句语法:order by column range|rows between 边界规则1 and 边界规则2,红色标记部分用来定位聚合计算范围,又被称为定位框架。

    rows表示按照行的范围进行范围的定义,range表示按照值的范围进行范围的定义,边界规则的可取值如下:

    示例1:按工资排序,并求第一行到当前行的累计工资。

    SELECT *,SUM(salary) OVER(ORDER BY salary ROWS BETWEEN unbounded preceding AND current ROW) 累计工资 FROM worker;
    

    ROWS BETWEEN unbounded preceding AND current ROW是开窗函数中最常使用的定位框架,表示从第一行到当前行。

    示例2:将示例中的row改成range,如下

    /*方法1*/SELECT *,SUM(salary) OVER(ORDER BY salary RANGE BETWEEN unbounded preceding AND current ROW) 累计工资 FROM worker;
    /*方法2*/SELECT *,SUM(salary) OVER(ORDER BY salary) 累计工资 FROM worker;

    rows是按行定位,range是按值定位,这两个不同的定位方式主要在于处理并列排序的情况。

    4、over(partition by column order by column)

    partition by和order by结合使用

    二、排名开窗函数

    主要有三个,ROW_NUMBER()、RANK()、DENSE_RANK(),它们的主要区别在于对并列值的处理规则不同。

    使用上述三个函数,对员工信息表按照工资排序,sql语句和输出结果如下。

    SELECT *,
    ROW_NUMBER() OVER(ORDER BY salary) rownumber_salary ,
    RANK() OVER(ORDER BY salary) rank_salary,
    DENSE_RANK() OVER(ORDER BY salary) dense_rank_salary
    FROM worker;

    ROW_NUMBER():不处理并列的情况,得到的结果连续递增。

    RANK():相同的值排序相同,但接下来的序号会跳过

    DENSE_RANK():相同的值排序相同,接下来的序号顺序递增

  • 相关阅读:
    晶振及COMS电路
    笔记16 C# typeof() & GetType()
    笔记15 修饰符
    笔记14 数据库编程技术
    C#基础知识
    C#连接数据库
    笔记13 winform
    笔记12 export to excel (NPOI)
    笔记11 export to excel
    笔记10
  • 原文地址:https://www.cnblogs.com/Forever77/p/15646556.html
Copyright © 2011-2022 走看看