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():相同的值排序相同,接下来的序号顺序递增

  • 相关阅读:
    leetcode 48. Rotate Image
    leetcode 203. Remove Linked List Elements 、83. Remove Duplicates from Sorted List 、82. Remove Duplicates from Sorted List II(剑指offer57 删除链表中重复的结点) 、26/80. Remove Duplicates from Sorted ArrayI、II
    leetcode 263. Ugly Number 、264. Ugly Number II 、313. Super Ugly Number 、204. Count Primes
    leetcode 58. Length of Last Word
    安卓操作的一些问题解决
    leetcode 378. Kth Smallest Element in a Sorted Matrix
    android studio Gradle Build速度加快方法
    禁用gridview,listview回弹或下拉悬停
    Android Studio找不到FragmentActivity类
    安卓获取ListView、GridView等滚动的距离(高度)
  • 原文地址:https://www.cnblogs.com/Forever77/p/15646556.html
Copyright © 2011-2022 走看看