什么是窗口函数

Window Function 也称为 OLAP(Online Analytical Processing)函数

是标准的 SQL 功能

窗口函数 ,或者 开窗函数 ,在 Oracle 中也称 分析函数

聚合函数 一样,也是对集合进行聚合计算,但和 聚合函数 又不一样,使用 聚合函数 时,每组只返回一个值,但 开窗函数

  你们懂我说的意思吧

mysql不支持date_add_mysql不支持date_add

  现在不懂也没关系哈,继续往下看,看完之后你肯定就懂了

窗口函数 是 标准 SQL 功能

Oracle 11g 、 SQL Server 2008 、 DB2 9.7 、 PostgreSQL 8.4

MySQL 从 8 开始才支持, MySQL5.7 及之前的版本不支持 窗口函数

SQL

SQL 终将能在所有的 DBMS

窗口函数的语法

  基本语法如下

mysql不支持date_add_SQL_02

  看着很简单,但却很陌生,我们将其进行拆分下

窗口函数

OVER 子句, OVER 是约定好的固定写法,其内容是规则的指定,告诉 窗口函数

PARTITION BY 类似 GROUP BY

ORDER BY 就跟我们平时使用的 ORDER BY

  看完这个语法介绍,我相信大家还是很懵,我非常理解大家

mysql不支持date_add_聚合函数_03

  但先别慌,结合案例来看,慢慢就懂了

  能够作为窗口函数使用的函数分两种

RANK 、 ROW_NUMBER 、  DENSE_RANK

SUM 、 AVG 、 COUNT 、 MAX 、 MIN

MySQL8.0.30 ,初始表 tbl_ware

mysql不支持date_add_SQL_04

mysql不支持date_add_SQL_05

mysql不支持date_add_窗口函数_06

CREATE TABLE `tbl_ware` (
  `ware_id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '商品id',
  `ware_name` VARCHAR(100) NOT NULL COMMENT '商品名称',
  `ware_category` VARCHAR(100) NOT NULL COMMENT '商品类别',
    `sale_unit_price` INT COMMENT '销售单价',
    `purchase_unit_price` INT COMMENT '进货单价',
    `registration_date` DATE COMMENT '等级日期',
  PRIMARY KEY (`ware_id`) USING BTREE
) ENGINE=InnoDB COMMENT='产品';

INSERT INTO tbl_ware VALUES
(1,'T恤衫','衣服',100, 50,'2023-12-15'),
(2,'打孔器','办公用品',25, 10,'2023-12-15'),
(3,'运动T恤','衣服',150, 50,'2023-12-15'),
(4,'菜刀','厨房用具',75, 30,'2023-12-15'),
(5,'高压锅','厨房用具',600, 200,'2023-12-15'),
(6,'叉子','厨房用具',7, 3,'2023-12-15'),
(7,'菜板','厨房用具',98, 30,'2023-12-15'),
(8,'圆珠笔','办公用品',5, 2,'2023-12-15');

mysql不支持date_add_聚合函数_07

View Code

专用窗口函数

SQL 定义的 OLAP 专用函数,通过函数名很容易看出其 OLAP

  从名字可知,该函数用来排名、排序

tbl_ware 按售价从高到低进行排名, SQL

SELECT * FROM tbl_ware ORDER BY sale_unit_price DESC;

RANK 也能实现: SELECT *, RANK() OVER(ORDER BY sale_unit_price DESC) AS ranking FROM

mysql不支持date_add_聚合函数_08

tbl_ware 按类别进行分组,然后组内按售价从高到低进行排名, SQL

GROUP BY

GROUP BY 往往结合 聚合函数

RANK 可以: SELECT *, RANK() OVER(PARTITION BY ware_category ORDER BY sale_unit_price DESC) AS ranking FROM

mysql不支持date_add_窗口函数_09

PARTITION BY 对表的横向进行分组,类似 GROUP BY

ORDER BY 则决定了纵向排序的规则,与 SELECT 子句末尾的 ORDER BY

PARTITION BY 分组后的记录集合称为“窗口”,代表“范围”。这也是 窗口函数

RANK

mysql不支持date_add_SQL_04

mysql不支持date_add_SQL_05

INSERT INTO tbl_ware VALUES
(9,'带帽卫衣','衣服', 150, 90, '2023-12-15'),
(10,'砍骨刀','厨房用具', 150, 69, '2023-12-15');

View Code

mysql不支持date_add_窗口函数_12

RANK 排序时,如果存在相同位次的记录,会跳过之后的位次,如: 1,2,2,2,5 , 3,4

DENSE_RANK 排序时,如果存在相同位次的记录,则不会跳过之后的位次,如: 1,2,2,2,3,4

  获取行数或者行号

SQL 可写成: SELECT *, ROW_NUMBER() OVER(ORDER BY sale_unit_price DESC) AS row_num FROM

mysql不支持date_add_窗口函数_13

SELECT *, ROW_NUMBER() OVER(PARTITION BY ware_category ORDER BY sale_unit_price DESC) AS row_num FROM

mysql不支持date_add_聚合函数_14

  此刻大家应该想起点什么了

mysql不支持date_add_窗口函数_15

  分组取前N条,是不是很适合用这种方式实现?

  我都跟你们实现好了:MySQL 分组排序后 → 如何取前N条或倒数N条

专用窗口函数

聚合函数的窗口化使用

聚合函数 都能用作窗口函数,其语法和 专用窗口函数

聚合函数

聚合函数 , SUM

  但是窗口化之后了,我们来看看效果

mysql不支持date_add_聚合函数_16

  发现什么了?

  并不是一个单独的汇总值,而是逐行汇总,是不是有点意思?

  如果再加上分组

mysql不支持date_add_聚合函数_17

  分组后,对每一组进行逐行汇总

SUM

mysql不支持date_add_窗口函数_18

  分组后,对每一组的每一行求历史平均值

聚合函数

窗口函数的适用范围

  通过上述的几个案例,相信大家对这个问题已经有了一个大致的答案

窗口函数 只能在 SELECT 子句中使用,不能在 WHERE 子句或者 GROUP BY

窗口函数 是对 WHERE 子句或者 GROUP BY

窗口函数 是不会改变结果行数的,而 WHERE 是会改变结果行数的,那把 窗口函数 放到 WHERE

窗口函数 只能在 SELECT

总结

窗口函数 是标准的 SQL

SQL

    提供了标准,数据库厂商不一定实现,或者说暂时不实现

窗口函数 与 聚合函数

窗口函数

窗口函数

参考

  《SQL 基础教程》

 


=======================================================================================

什么是窗口函数

Window Function 也称为 OLAP(Online Analytical Processing)函数

是标准的 SQL 功能

窗口函数 ,或者 开窗函数 ,在 Oracle 中也称 分析函数

聚合函数 一样,也是对集合进行聚合计算,但和 聚合函数 又不一样,使用 聚合函数 时,每组只返回一个值,但 开窗函数

  你们懂我说的意思吧

mysql不支持date_add_mysql不支持date_add

  现在不懂也没关系哈,继续往下看,看完之后你肯定就懂了

窗口函数 是 标准 SQL 功能

Oracle 11g 、 SQL Server 2008 、 DB2 9.7 、 PostgreSQL 8.4

MySQL 从 8 开始才支持, MySQL5.7 及之前的版本不支持 窗口函数

SQL

SQL 终将能在所有的 DBMS

窗口函数的语法

  基本语法如下

mysql不支持date_add_SQL_02

  看着很简单,但却很陌生,我们将其进行拆分下

窗口函数

OVER 子句, OVER 是约定好的固定写法,其内容是规则的指定,告诉 窗口函数

PARTITION BY 类似 GROUP BY

ORDER BY 就跟我们平时使用的 ORDER BY

  看完这个语法介绍,我相信大家还是很懵,我非常理解大家

mysql不支持date_add_聚合函数_03

  但先别慌,结合案例来看,慢慢就懂了

  能够作为窗口函数使用的函数分两种

RANK 、 ROW_NUMBER 、  DENSE_RANK

SUM 、 AVG 、 COUNT 、 MAX 、 MIN

MySQL8.0.30 ,初始表 tbl_ware

mysql不支持date_add_SQL_04

mysql不支持date_add_SQL_05

mysql不支持date_add_mysql不支持date_add_24

CREATE TABLE `tbl_ware` (
  `ware_id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '商品id',
  `ware_name` VARCHAR(100) NOT NULL COMMENT '商品名称',
  `ware_category` VARCHAR(100) NOT NULL COMMENT '商品类别',
    `sale_unit_price` INT COMMENT '销售单价',
    `purchase_unit_price` INT COMMENT '进货单价',
    `registration_date` DATE COMMENT '等级日期',
  PRIMARY KEY (`ware_id`) USING BTREE
) ENGINE=InnoDB COMMENT='产品';

INSERT INTO tbl_ware VALUES
(1,'T恤衫','衣服',100, 50,'2023-12-15'),
(2,'打孔器','办公用品',25, 10,'2023-12-15'),
(3,'运动T恤','衣服',150, 50,'2023-12-15'),
(4,'菜刀','厨房用具',75, 30,'2023-12-15'),
(5,'高压锅','厨房用具',600, 200,'2023-12-15'),
(6,'叉子','厨房用具',7, 3,'2023-12-15'),
(7,'菜板','厨房用具',98, 30,'2023-12-15'),
(8,'圆珠笔','办公用品',5, 2,'2023-12-15');

mysql不支持date_add_聚合函数_25

View Code

专用窗口函数

SQL 定义的 OLAP 专用函数,通过函数名很容易看出其 OLAP

  从名字可知,该函数用来排名、排序

tbl_ware 按售价从高到低进行排名, SQL

SELECT * FROM tbl_ware ORDER BY sale_unit_price DESC;

RANK 也能实现: SELECT *, RANK() OVER(ORDER BY sale_unit_price DESC) AS ranking FROM

mysql不支持date_add_聚合函数_08

tbl_ware 按类别进行分组,然后组内按售价从高到低进行排名, SQL

GROUP BY

GROUP BY 往往结合 聚合函数

RANK 可以: SELECT *, RANK() OVER(PARTITION BY ware_category ORDER BY sale_unit_price DESC) AS ranking FROM

mysql不支持date_add_窗口函数_09

PARTITION BY 对表的横向进行分组,类似 GROUP BY

ORDER BY 则决定了纵向排序的规则,与 SELECT 子句末尾的 ORDER BY

PARTITION BY 分组后的记录集合称为“窗口”,代表“范围”。这也是 窗口函数

RANK

mysql不支持date_add_SQL_04

mysql不支持date_add_SQL_05

INSERT INTO tbl_ware VALUES
(9,'带帽卫衣','衣服', 150, 90, '2023-12-15'),
(10,'砍骨刀','厨房用具', 150, 69, '2023-12-15');

View Code

mysql不支持date_add_窗口函数_12

RANK 排序时,如果存在相同位次的记录,会跳过之后的位次,如: 1,2,2,2,5 , 3,4

DENSE_RANK 排序时,如果存在相同位次的记录,则不会跳过之后的位次,如: 1,2,2,2,3,4

  获取行数或者行号

SQL 可写成: SELECT *, ROW_NUMBER() OVER(ORDER BY sale_unit_price DESC) AS row_num FROM

mysql不支持date_add_窗口函数_13

SELECT *, ROW_NUMBER() OVER(PARTITION BY ware_category ORDER BY sale_unit_price DESC) AS row_num FROM

mysql不支持date_add_聚合函数_14

  此刻大家应该想起点什么了

mysql不支持date_add_窗口函数_15

  分组取前N条,是不是很适合用这种方式实现?

  我都跟你们实现好了:MySQL 分组排序后 → 如何取前N条或倒数N条

专用窗口函数

聚合函数的窗口化使用

聚合函数 都能用作窗口函数,其语法和 专用窗口函数

聚合函数

聚合函数 , SUM

  但是窗口化之后了,我们来看看效果

mysql不支持date_add_聚合函数_16

  发现什么了?

  并不是一个单独的汇总值,而是逐行汇总,是不是有点意思?

  如果再加上分组

mysql不支持date_add_聚合函数_17

  分组后,对每一组进行逐行汇总

SUM

mysql不支持date_add_窗口函数_18

  分组后,对每一组的每一行求历史平均值

聚合函数

窗口函数的适用范围

  通过上述的几个案例,相信大家对这个问题已经有了一个大致的答案

窗口函数 只能在 SELECT 子句中使用,不能在 WHERE 子句或者 GROUP BY

窗口函数 是对 WHERE 子句或者 GROUP BY

窗口函数 是不会改变结果行数的,而 WHERE 是会改变结果行数的,那把 窗口函数 放到 WHERE

窗口函数 只能在 SELECT

总结

窗口函数 是标准的 SQL

SQL

    提供了标准,数据库厂商不一定实现,或者说暂时不实现

窗口函数 与 聚合函数

窗口函数

窗口函数

参考

  《SQL 基础教程》