【MySQL】MySQL 8.0 新特性之 - 窗口函数(Window Functions)

1. 定义

1.1 窗口函数

官网地址:https://dev.mysql.com/doc/refman/8.0/en/window-functions.html

窗口可以理解为记录集合,窗口函数就是在满足某种条件的记录集合上执行的特殊函数。
即:每条记录都要在此窗口内执行函数

  • 静态窗口:每条记录都要在此窗口内执行函数,窗口大小都是固定的

  • 动态窗口:不同的记录对应着不同的窗口,这种动态变化的窗口叫滑动窗口。

窗口函数也称为 OLAP(Online Anallytical Processing)函数,意思是对数据库数据进行实时分析处理。窗口函数就是为了实现 OLAP 而添加的标准 SQL 功能。

窗口函数对一组查询行执行类似聚合的操作。然而,聚合操作将查询行分组为单个结果行,而窗口函数为每个查询行生成一个结果

  • 发生函数计算的行称为当前行。

  • 与对其进行函数计算的当前行相关的查询行构成当前行的窗口。

在这里插入图片描述

1.2 语法格式

函数名(字段名) over(子句);

over 括号内若不写,则意味着窗口函数基于满足 where 条件的所有行进行计算;

若括号内不为空,则支持以下语法来设置窗口:

函数名(字段名) over(partition by <要分列的组> order by <要排序的列> rows between <数据范围>) 

数据范围:

# 取本行和前面两行
rows between 2 preceding and current row

# 取本行和之前所有的行
rows between unbounded preceding and current row

# 取本行和之后所有的行
rows between current row and unbounded following 

# 从前面三行和下面一行,总共五行
rows between 3 preceding and 1 following 

# 当 order by 后面没有 rows between 时,窗口规范默认是取本行和之前所有的行

# 当 order by 和 rows between 都没有时,窗口规范默认是分组下所有行 (rows between unbounded preceding and unbounded following)

2. 分类

2.1 序号函数

序号函数是按照一定的分组规则对每一组的数据排序并创建一个序号列。

2.1.1 row_number()

单纯的对每一组数据编号,进行顺序显示。

2.1.2 rank()

排序每一组的某一字段, 同等级同序号前后不连续。

对序号进行并列排序,指定字段数值相同(同一等级),则会产生相同序号记录,且产生序号间隙。

rank 函数没有参数,但需要指定按照那个字段进行排名,所以使用 rank 函数必须用 order by 参数,order by 的排序字段就是排名字段。

2.1.3 dense_rank()

排序每一组的某一字段, 同等级同序号前后也连续。

对序号进行并列排序,指定字段数值相同(同一等级)则会产生相同序号记录,且产生序号间隙。

2.2.4 示例

# 查询显示列中一组值的每个成员的排名值 val
mysql> SELECT
         val,
         ROW_NUMBER() OVER w AS 'row_number',
         RANK()       OVER w AS 'rank',
         DENSE_RANK() OVER w AS 'dense_rank'
       FROM numbers
       WINDOW w AS (ORDER BY val);
+------+------------+------+------------+
| val  | row_number | rank | dense_rank |
+------+------------+------+------------+
|    1 |          1 |    1 |          1 |
|    1 |          2 |    1 |          1 |
|    2 |          3 |    3 |          2 |
|    3 |          4 |    4 |          3 |
|    3 |          5 |    4 |          3 |
|    3 |          6 |    4 |          3 |
|    4 |          7 |    7 |          4 |
|    4 |          8 |    7 |          4 |
|    5 |          9 |    9 |          5 |
+------+------------+------+------------+

2.2 分布函数

分布函数有:percent_rank()、cume_dist()

2.2.1 percent_rank()

计算分区或结果集中行的百分位数排名。

每行按照公式 (rank-1)/ (rows-1) 进行计算。其中,rank 为 RANK() 函数产生的序号,rows 为当前窗口(当前组)的总行数。

2.2.2 cume_dist()

累积分布值,<= 当前 rank 值的行数 / 分组内总行数,取值范围为 0~1。

应用场景:查询小于等于当前成绩(score)的比例。

示例:

mysql> SELECT
         val,
         ROW_NUMBER()   OVER w AS 'row_number',
         CUME_DIST()    OVER w AS 'cume_dist',
         PERCENT_RANK() OVER w AS 'percent_rank'
       FROM numbers
       WINDOW w AS (ORDER BY val);
+------+------------+--------------------+--------------+
| val  | row_number | cume_dist          | percent_rank |
+------+------------+--------------------+--------------+
|    1 |          1 | 0.2222222222222222 |            0 |
|    1 |          2 | 0.2222222222222222 |            0 |
|    2 |          3 | 0.3333333333333333 |         0.25 |
|    3 |          4 | 0.6666666666666666 |        0.375 |
|    3 |          5 | 0.6666666666666666 |        0.375 |
|    3 |          6 | 0.6666666666666666 |        0.375 |
|    4 |          7 | 0.8888888888888888 |         0.75 |
|    4 |          8 | 0.8888888888888888 |         0.75 |
|    5 |          9 |                  1 |            1 |
+------+------------+--------------------+--------------+

2.3 前后函数

2.3.1 lag(expr, n, default)

返回当前行前 n 行的 expr 值。n 如果没有这样的行,则返回值为 default。如果缺少 n 或 default,则默认值分别为 1 或 NULL。

n 必须是非负整数。如果 n 为 0, expr 则为当前行的值。

从 MySQL 8.0.22 开始,n 不能 NULL。此外,它必须是1 到 2的63次方 的整数。

2.3.2 lead(expr, n, default)

返回当前行后 n 行的 expr 值。n 如果没有这样的行,则返回值为 default。如果缺少 n 或 default,则默认值分别为 1 或 NULL。

n 必须是非负整数。如果 n 为 0, expr 则为当前行的值。

从 MySQL 8.0.22 开始,n 不能 NULL。此外,它必须是1 到 2的63次方 的整数。

2.3.3 示例

mysql> SELECT
         t, val,
         LAG(val)        OVER w AS 'lag',
         LEAD(val)       OVER w AS 'lead',
         val - LAG(val)  OVER w AS 'lag diff',
         val - LEAD(val) OVER w AS 'lead diff'
       FROM series
       WINDOW w AS (ORDER BY t);
+----------+------+------+------+----------+-----------+
| t        | val  | lag  | lead | lag diff | lead diff |
+----------+------+------+------+----------+-----------+
| 12:00:00 |  100 | NULL |  125 |     NULL |       -25 |
| 13:00:00 |  125 |  100 |  132 |       25 |        -7 |
| 14:00:00 |  132 |  125 |  145 |        7 |       -13 |
| 15:00:00 |  145 |  132 |  140 |       13 |         5 |
| 16:00:00 |  140 |  145 |  150 |       -5 |       -10 |
| 17:00:00 |  150 |  140 |  200 |       10 |       -50 |
| 18:00:00 |  200 |  150 | NULL |       50 |      NULL |
+----------+------+------+------+----------+-----------+

2.4 头尾函数

2.4.1 first_value(expr)

first_value 取分组内排序后,截止到当前行,第一个值。

2.4.2 last_value(expr)

last_value 取分组内排序后,截止到当前行,最后一个值。

2.4.3 示例

mysql> SELECT
         time, subject, val,
         FIRST_VALUE(val)  OVER w AS 'first',
         LAST_VALUE(val)   OVER w AS 'last',
         NTH_VALUE(val, 2) OVER w AS 'second',
         NTH_VALUE(val, 4) OVER w AS 'fourth'
       FROM observations
       WINDOW w AS (PARTITION BY subject ORDER BY time
                    ROWS UNBOUNDED PRECEDING);
+----------+---------+------+-------+------+--------+--------+
| time     | subject | val  | first | last | second | fourth |
+----------+---------+------+-------+------+--------+--------+
| 07:00:00 | st113   |   10 |    10 |   10 |   NULL |   NULL |
| 07:15:00 | st113   |    9 |    10 |    9 |      9 |   NULL |
| 07:30:00 | st113   |   25 |    10 |   25 |      9 |   NULL |
| 07:45:00 | st113   |   20 |    10 |   20 |      9 |     20 |
| 07:00:00 | xh458   |    0 |     0 |    0 |   NULL |   NULL |
| 07:15:00 | xh458   |   10 |     0 |   10 |     10 |   NULL |
| 07:30:00 | xh458   |    5 |     0 |    5 |     10 |   NULL |
| 07:45:00 | xh458   |   30 |     0 |   30 |     10 |     30 |
| 08:00:00 | xh458   |   25 |     0 |   25 |     10 |     30 |
+----------+---------+------+-------+------+--------+--------+

2.5 其他函数

2.5.1 nth_value(expr, n)

nth_value 函数返回第 n 行的 expr 值,没有则返回 null。

2.5.2 ntile(n)

ntile 函数将分区中的有序数据分为 n 个桶,记录桶编号。

2.5.3 示例

mysql> SELECT
         val,
         ROW_NUMBER() OVER w AS 'row_number',
         NTILE(2)     OVER w AS 'ntile2',
         NTILE(4)     OVER w AS 'ntile4'
       FROM numbers
       WINDOW w AS (ORDER BY val);
+------+------------+--------+--------+
| val  | row_number | ntile2 | ntile4 |
+------+------------+--------+--------+
|    1 |          1 |      1 |      1 |
|    1 |          2 |      1 |      1 |
|    2 |          3 |      1 |      1 |
|    3 |          4 |      1 |      2 |
|    3 |          5 |      1 |      2 |
|    3 |          6 |      2 |      3 |
|    4 |          7 |      2 |      3 |
|    4 |          8 |      2 |      4 |
|    5 |          9 |      2 |      4 |
+------+------------+--------+--------+

2.6 聚合类窗口函数

sum() over( partion by <要分列的组> order by <要排序的列> rows between <数据范围> )

count() over( partion by <要分列的组> order by <要排序的列> rows between <数据范围> )

avg() over( partion by <要分列的组> order by <要排序的列> rows between <数据范围> )

max() over( partion by <要分列的组> order by <要排序的列> rows between <数据范围> )

min() over( partion by <要分列的组> order by <要排序的列> rows between <数据范围> )

  • 7
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论
1. Window functions: MySQL 8.0 now supports window functions, which allows users to perform complex analytical queries with ease. 2. Common Table Expressions (CTEs): CTEs are temporary result sets that can be used within a single SQL statement. This feature makes it easier to write complex queries and improves code readability. 3. Recursive Common Table Expressions (RCTEs): RCTEs are a special type of CTE that allows users to write recursive queries. This feature is useful for queries that involve hierarchical data. 4. JSON enhancements: MySQL 8.0 includes several enhancements to its JSON support, including better performance and improved functionality. 5. Invisible indexes: This feature allows users to mark an index as "invisible," which means that it will not be used by the query optimizer. This can be useful for testing the impact of removing an index without actually removing it. 6. Instant ADD COLUMN: MySQL 8.0 includes a new feature that allows users to add a new column to a table without copying the entire table. This can be useful for large tables with many columns. 7. Roles: MySQL 8.0 introduces the concept of roles, which allows users to define sets of privileges that can be assigned to multiple users. 8. Improved performance: MySQL 8.0 includes several performance improvements, including better support for multi-threaded queries and faster data loading. 9. Improved security: MySQL 8.0 includes several security enhancements, including improved password management and support for encrypted connections. 10. Improved replication: MySQL 8.0 includes several improvements to its replication capabilities, including support for multiple replication channels and better conflict detection and resolution.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奥特迦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值