从version 8.0开始,MySQL支持在查询中使用窗口函数。这篇文章是对一篇英文资料的不完全翻译,加上自己的一些理解。如果有兴趣可以去看看原文章。文中的示例用到的建表语句和插值语句如下:

CREATE TABLE sales(sales_employee VARCHAR(50) NOT NULL,fiscal_year INT NOT NULL,sale DECIMAL(14,2) NOT NULL,PRIMARY KEY(sales_employee,fiscal_year)
);INSERT INTO sales(sales_employee,fiscal_year,sale)
VALUES('Bob',2016,100),('Bob',2017,150),('Bob',2018,200),('Alice',2016,150),('Alice',2017,100),('Alice',2018,200),('John',2016,200),('John',2017,150),('John',2018,250);

先看一个例子:

SELECT fiscal_year, sales_employee,sale,SUM(sale) OVER (PARTITION BY fiscal_year) total_sales
FROMsales;

执行后得到的结果如下:

+-------------+----------------+--------+-------------+
| fiscal_year | sales_employee | sale   | total_sales |
+-------------+----------------+--------+-------------+
|        2016 | Alice          | 150.00 |      450.00 |
|        2016 | Bob            | 100.00 |      450.00 |
|        2016 | John           | 200.00 |      450.00 |
|        2017 | Alice          | 100.00 |      400.00 |
|        2017 | Bob            | 150.00 |      400.00 |
|        2017 | John           | 150.00 |      400.00 |
|        2018 | Alice          | 200.00 |      650.00 |
|        2018 | Bob            | 200.00 |      650.00 |
|        2018 | John           | 250.00 |      650.00 |
+-------------+----------------+--------+-------------+
9 rows in set (0.00 sec)

这里,sum()函数充当了窗口函数,得到了根据fiscal_year计算出的sale的总和total_sales列,但是又不像它作为聚合函数使用时一样,这里的结果保留了每一行的信息。
原因就在于窗口函数的执行顺序(逻辑上的)是在FROM,JOIN,WHERE,GROUP BY,HAVING之后,在ORDER BY,LIMIT,SELECT DISTINCT之前。它执行时GROUP BY的聚合过程已经完成了,所以不会再产生数据聚合。

窗口函数的语法

窗口函数的语法是

window_function_name(expression) OVER ([partition_defintion][order_definition][frame_definition])

先指定作为窗口函数的函数名,然后是OVER(…),就算OVER里面没有内容,括号也需要保留。
窗口函数的一个概念是当前行,当前行属于某个窗口,窗口由“[partition_defintion]”,“[order_definition]”,“[frame_definition]“确定。

  1. partition_defintion
    翻译过来应该是分区,语法是"PARTITION BY < expression>[{,< expression>…}]",它会根据单个或者多个表达式的计算结果来分区(列名也是一种表达式,它的结果就是列名本身)。在前面的例子中,结果中的每一行都有自己的分区,total_sales列的值就是它所属的分区里面的sum(sale)的结果。
  2. frame_definition
    这里先讲frame_definition,可能应该是叫帧吧。它的作用是在分区里面再进一步细分窗口。语法是"frame_unit {< frame_start>|< frame_between>}",frame_unit有两种,分别是ROWS和RANGE,由ROWS定义的frame是由开始和结束位置的行确定的,由RANGE定义的frame由在某个值区间的行确定。
    如果只指定了frame的开始位置,那么结束位置就默认为当前行。frame_start有三种:
  • UNBOUNDED PRECEDING: 区间的第一行
  • N PRECEDING: 当前行之前的N行,N可以是数字,也可以是一个能计算出数字的表达式
  • CURRENT ROW: 当前行

frame_between的可以取的值如下:

  • frame_start:如前面所列
  • UNBOUNDED FOLLOWING:区间的最后一行
  • N FOLLOWING:当前行之后的N行,N可以是数字,也可以是一个能计算出数字的表达式
    如果没显式指定frame的话,MySQL会认为frame是“ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING”

这个有点复杂,看个例子:

SELECT fiscal_year, sales_employee,sale,SUM(sale) OVER (PARTITION BY sales_employee ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) total_sales
FROMsales;

执行结果如下:

+-------------+----------------+--------+-------------+
| fiscal_year | sales_employee | sale   | total_sales |
+-------------+----------------+--------+-------------+
|        2016 | Alice          | 150.00 |      150.00 |
|        2017 | Alice          | 100.00 |      250.00 |
|        2018 | Alice          | 200.00 |      450.00 |
|        2016 | Bob            | 100.00 |      100.00 |
|        2017 | Bob            | 150.00 |      250.00 |
|        2018 | Bob            | 200.00 |      450.00 |
|        2016 | John           | 200.00 |      200.00 |
|        2017 | John           | 150.00 |      350.00 |
|        2018 | John           | 250.00 |      600.00 |
+-------------+----------------+--------+-------------+
9 rows in set (0.00 sec)

第一行所在的区间是sales_employee为Alice的区间,所在的帧是区间第一行到当前行,只有一行,total_sales为150;第二行所在的区间是sales_employee为Alice的区间,所在的帧是区间第一行到当前行,有两行,total_sales为150+100=250;第一行所在的区间是sales_employee为Alice的区间,所在的帧是区间第一行到当前行,有三行,total_sales为150+100+200=450。

  1. order_definition
    定义了分区内的行的排列顺序,语法是“ORDER BY < expression> [ASC|DESC], [{,< expression>…}]”。没什么好讲的。

MySQL中的窗口函数相关推荐

  1. mysql中还有窗口函数?这是什么东西?

    什么是窗口函数? 在mysql8.0的版本中,新增了一个窗口函数,用他可以实现很多新的查询方式.窗口函数类似于sun().count()那样的集合函数,但它并不会将多行查询结果合并为一行,而是将结果放 ...

  2. mysql over rank_sql - MySQL中的Rank函数

    sql - MySQL中的Rank函数 我需要找出客户的排名. 在这里,我为我的要求添加了相应的ANSI标准SQL查询. 请帮我转换为MySQL. SELECT RANK() OVER (PARTIT ...

  3. MySQL中的sum函数用法实例详解

    今天分享一下mysql中的sum函数使用.该函数已经成为大家操作mysql数据库中时常用到的一个函数,这个函数统计满足条件行中指定列的和,想必肯定大家都知道了,本身就没什么讲头了,这篇文章主要是通过几 ...

  4. 「数据分析」Sqlserver中的窗口函数的精彩应用之数据差距与数据岛(含答案)...

    上一篇介绍过数据差距与数据岛的背景,这里不再赘述,请翻阅上一文.此篇在Sqlserver上给大家演示1000万条记录的计算性能. 测试电脑软硬件说明 一般般的笔记本电脑,2017年7月,价格:4500 ...

  5. sql查询三级菜单分类_SQL面试50题——思路解答与分类整理(中)窗口函数与子查询...

    让我们每天都进步一点点 题目快速查找索引 阅读指南 上篇:SQL面试50题--思路解答与分类整理(上)聚合函数与表连接 [第一部分]聚合函数(sum/avg/count/min/max) [第二部分] ...

  6. MySQL 8.0窗口函数

    团队介绍 网易乐得DBA组,负责网易乐得电商.网易邮箱.网易技术部数据库日常运维,负责数据库私有云平台的开发和维护,负责数据库及数据库中间件Cetus的开发和测试等等. 一.窗口函数的使用场景 作为I ...

  7. Mysql 不使用窗口函数实现分组排序 rank 别名问题

    Mysql 不使用窗口函数实现分组排序 变量 定义和修改 方法1 set @变量名:=值: set @name="bob"; set @name="jojo"; ...

  8. MySQL中查询中位数?

    导读 计算中位数可能是小学的内容,然而在数据库查询中实现却并不是一件容易的事.我们今天就来看看都有哪些方法可以实现. 注:本文所用MySQL版本无限制,所列题目均来源于LeetCode. LeetCo ...

  9. SQL 中的窗口函数

    SQL 中的窗口函数(Window Functions)是一种特殊的函数,它可以在查询结果的某个区间内执行计算,而不仅仅是对单个行进行计算. 以下是一些常用的窗口函数: 1.ROW_NUMBER() ...

  10. MySql中@符号的使用

    MySql中@符号的使用 @符号的作用 @后接变量名,用以定义一个变量,该变量的有效期为语句级,即再一次执行中始终有效,基本示例如下: -- 由于通常情况下=被认为是等于比较运算符,因此赋值运算符一般 ...

最新文章

  1. Java项目:OA办公自动化系统设计和实现(java+springboot+freemarker+mysql+maven+mybatis+jpa)
  2. 模板方法模式与策略模式的区别
  3. bal插口_EBS R12各模块接口表大全
  4. Hadoop组件基本操作
  5. JS原生封装动画函数
  6. [剑指offer]面试题第[43]题[Leetcode][第233题][JAVA][1~n整数中1出现的次数][找规律][递归]
  7. axis2开发webservice之编写Axis2模块(Module)
  8. 系统软键盘Android在外接物理键盘时,如何强制调用系统软键盘?
  9. ThreadPoolExecutor执行过程分析
  10. 【SimpleITK】Resampling重采样
  11. 利用循环打印正方形和长方形
  12. 细数处女座的101个特质
  13. codeforces1467E. Distinctive Roots in a Tree
  14. pr cpu100%_PR插件NewBlueFX Titler Pro6.0安装教程
  15. 最后1天!生信入门转录组和可视化学习捷径
  16. 用html css JavaScript写一个功能全面的王者荣耀轮播图 (仿淘宝京东轮播图)通俗易懂
  17. NetHunter-Rootless:安卓手机免Root安装Kali NetHunter
  18. 西门子et200 分布式i/o_西门子S7-1500H冗余系统硬件及网络结构
  19. cesium建筑物3DTile单体化(cesium篇.24)
  20. 【搜集+亲测】无法注册Flash Player的Activex控件最终解决方法(亲测,WIN7 64位系统)

热门文章

  1. PKG安装包的管理与文件格式分析
  2. Mac中如何卸载pkg包
  3. ES安装以及基本应用
  4. 原生开发什么意思_原生App是什么意思
  5. ubuntu server 20.04安装vnc远程桌面xfce4
  6. 500报错及故障排除
  7. 鼠标悬浮显示小手可抓取(CSS伪类)
  8. python实现英雄联盟信息获取
  9. Pr——将视频画面旋转90度的一种方法
  10. 让canvas绘图更清晰