MySQL补充开窗函数

MySQL补充开窗函数

一.介绍

  • 在 SQL 中,开窗函数是一种强大的查询工具,它允许我们在查询中进行对分组数据进行计算、 同时保留原始行的详细信息 。
  • 开窗函数可以与聚合函数(如 SUM、AVG、COUNT 等)结合使用,但与普通聚合函数不同,开窗函数不会导致结果集的行数减少。

假设有一个学生表 student,包含以下字段:id(学号)、name(姓名)、age(年龄)、score(分数)、class_id(班级编号)。

sql 复制代码
mysql> select * from student;
+----+------+-----+--------+----------+
| id | name | age | score  | calss_id |
+----+------+-----+--------+----------+
|  1 | fuck |  18 | 11.000 |        3 |
|  2 | man  |  21 | 33.400 |        1 |
|  3 | yes  |  33 | 91.000 |        3 |
|  4 | NO   |  61 | 71.000 |        2 |
|  5 | bash |  44 | 41.500 |        1 |
|  6 | sql  |  91 | 10.500 |        2 |
+----+------+-----+--------+----------+
6 rows in set (0.00 sec)

窗口函数是在 MySQL 8.0 版本及以上引入的功能。

二.sum over

使用:sum(计算字段名) over (partition by 分组字段名)

请你编写一个 SQL 查询,返回每个学生的详细信息(字段顺序和原始表的字段顺序一致),并计算每个班级的学生平均分(class_avg_score)。

sql 复制代码
mysql> select * from student;
+----+------+-----+--------+----------+
| id | name | age | score  | calss_id |
+----+------+-----+--------+----------+
|  1 | fuck |  18 | 11.000 |        3 |
|  2 | man  |  21 | 33.400 |        1 |
|  3 | yes  |  33 | 91.000 |        3 |
|  4 | NO   |  61 | 71.000 |        2 |
|  5 | bash |  44 | 41.500 |        1 |
|  6 | sql  |  91 | 10.500 |        2 |
+----+------+-----+--------+----------+
6 rows in set (0.00 sec)

mysql> select *,avg(score) over (partition by calss_id) as class_avg_score from student;
+----+------+-----+--------+----------+-----------------+
| id | name | age | score  | calss_id | class_avg_score |
+----+------+-----+--------+----------+-----------------+
|  2 | man  |  21 | 33.400 |        1 |      37.4500000 |
|  5 | bash |  44 | 41.500 |        1 |      37.4500000 |
|  4 | NO   |  61 | 71.000 |        2 |      40.7500000 |
|  6 | sql  |  91 | 10.500 |        2 |      40.7500000 |
|  1 | fuck |  18 | 11.000 |        3 |      51.0000000 |
|  3 | yes  |  33 | 91.000 |        3 |      51.0000000 |
+----+------+-----+--------+----------+-----------------+
6 rows in set (0.01 sec)

三.sum over order by

可以实现同组内数据的累加求和 。
使用:sum(计算字段名) over (partition by分组字段名 order by 排序字段 排序规则)

请你编写一个 SQL 查询,返回每个学生的详细信息(字段顺序和原始表的字段顺序一致),并且按照分数升序的方式累加计算每个班级的学生总分(class_sum_score)。

sql 复制代码
mysql> select * from student;
+----+------+-----+--------+----------+
| id | name | age | score  | calss_id |
+----+------+-----+--------+----------+
|  1 | fuck |  18 | 11.000 |        3 |
|  2 | man  |  21 | 33.400 |        1 |
|  3 | yes  |  33 | 91.000 |        3 |
|  4 | NO   |  61 | 71.000 |        2 |
|  5 | bash |  44 | 41.500 |        1 |
|  6 | sql  |  91 | 10.500 |        2 |
+----+------+-----+--------+----------+
6 rows in set (0.00 sec)

mysql> select *,sum(score) over (partition by calss_id order by score asc) as class_sum_score from student
;
+----+------+-----+--------+----------+-----------------+
| id | name | age | score  | calss_id | class_sum_score |
+----+------+-----+--------+----------+-----------------+
|  2 | man  |  21 | 33.400 |        1 |          33.400 |
|  5 | bash |  44 | 41.500 |        1 |          74.900 |
|  6 | sql  |  91 | 10.500 |        2 |          10.500 |
|  4 | NO   |  61 | 71.000 |        2 |          81.500 |
|  1 | fuck |  18 | 11.000 |        3 |          11.000 |
|  3 | yes  |  33 | 91.000 |        3 |         102.000 |
+----+------+-----+--------+----------+-----------------+
6 rows in set (0.00 sec)

四.Rank

Rank 开窗函数是 SQL 中一种用于对查询结果集中的行进行 排名 的开窗函数。它可以根据指定的列或表达式对结果集中的行进行排序,并为每一行分配一个排名。在排名过程中,相同的值将被赋予相同的排名,而不同的值将被赋予不同的排名。

使用:

sql 复制代码
RANK() OVER (
  PARTITION BY 列名1, 列名2, ... -- 可选,用于指定分组列,将结果集按照指定列进行分组;
  ORDER BY 列名3 [ASC|DESC], 列名4 [ASC|DESC], ... -- 用于指定排序列及排序方式,决定了计算 Rank 时的排序规则
) AS rank_column --AS rank_column 用于指定生成的 Rank 排名列的别名。

请你编写一个 SQL 查询,返回每个学生的详细信息(字段顺序和原始表的字段顺序一致),并且按照分数降序的方式计算每个班级内的学生的分数排名(ranking)。

sql 复制代码
mysql> select * from student;
+----+------+-----+--------+----------+
| id | name | age | score  | calss_id |
+----+------+-----+--------+----------+
|  1 | fuck |  18 | 11.000 |        3 |
|  2 | man  |  21 | 33.400 |        1 |
|  3 | yes  |  33 | 91.000 |        3 |
|  4 | NO   |  61 | 71.000 |        2 |
|  5 | bash |  44 | 41.500 |        1 |
|  6 | sql  |  91 | 10.500 |        2 |
+----+------+-----+--------+----------+
6 rows in set (0.00 sec)

mysql> select *,rank() over (partition by calss_id order by score desc) as ranking from student;
+----+------+-----+--------+----------+---------+
| id | name | age | score  | calss_id | ranking |
+----+------+-----+--------+----------+---------+
|  5 | bash |  44 | 41.500 |        1 |       1 |
|  2 | man  |  21 | 33.400 |        1 |       2 |
|  4 | NO   |  61 | 71.000 |        2 |       1 |
|  6 | sql  |  91 | 10.500 |        2 |       2 |
|  3 | yes  |  33 | 91.000 |        3 |       1 |
|  1 | fuck |  18 | 11.000 |        3 |       2 |
+----+------+-----+--------+----------+---------+
6 rows in set (0.00 sec)

五.Row_Number

Row_Number开窗函数是 SQL 中的一种用于为查询结果集中的每一行分配唯一连续排名 的开窗函数。它与之前讲到的 Rank 函数,Row_Number 函数为每一行都分配一个唯一的整数值,不管是否存在并列(相同排序值)的情况。每一行都有一个唯一的行号,从 1 开始连续递增

使用: 与rank相同

请你编写一个 SQL 查询,返回每个学生的详细信息(字段顺序和原始表的字段顺序一致),并且按照分数降序的方式给每个班级内的学生分配一个编号(row_number)。

sql 复制代码
mysql> select * from student;
+----+------+-----+--------+----------+
| id | name | age | score  | calss_id |
+----+------+-----+--------+----------+
|  1 | fuck |  18 | 11.000 |        3 |
|  2 | man  |  21 | 33.400 |        1 |
|  3 | yes  |  33 | 91.000 |        3 |
|  4 | NO   |  61 | 71.000 |        2 |
|  5 | bash |  44 | 41.500 |        1 |
|  6 | sql  |  91 | 10.500 |        2 |
|  7 | a    |  38 | 11.000 |        3 |
+----+------+-----+--------+----------+
7 rows in set (0.00 sec)
sql 复制代码
mysql> select *,row_number() over (partition by calss_id order by score desc) as ow_number from student;
+----+------+-----+--------+----------+-----------+
| id | name | age | score  | calss_id | ow_number |
+----+------+-----+--------+----------+-----------+
|  5 | bash |  44 | 41.500 |        1 |         1 |
|  2 | man  |  21 | 33.400 |        1 |         2 |
|  4 | NO   |  61 | 71.000 |        2 |         1 |
|  6 | sql  |  91 | 10.500 |        2 |         2 |
|  3 | yes  |  33 | 91.000 |        3 |         1 |
|  1 | fuck |  18 | 11.000 |        3 |         2 |
|  7 | a    |  38 | 11.000 |        3 |         3 |
+----+------+-----+--------+----------+-----------+
7 rows in set (0.00 sec)

六.Lag 和 Lead

开窗函数 Lag 和 Lead 的作用是获取在当前行之前或之后的行的值,这两个函数通常在需要比较相邻行数据或进行时间序列分析时非常有用。

1.Lag 函数用于获取 当前行之前 的某一列的值。它可以帮助我们查看上一行的数据。

使用:lag(要获取值的列名, 向上偏移的行数, 可选参数用于指定当没有前一行时的默认值) over (partition by 分组字段名 order by 排序字段 排序规则)

2.Lead 函数用于获取 当前行之后 的某一列的值。它可以帮助我们查看下一行的数据。

使用:lag(要获取值的列名, 向下偏移的行数, 可选参数用于指定当没有后一行时的默认值) over (partition by 分组字段名 order by 排序字段 排序规则)

请你编写一个 SQL 查询,返回每个学生的详细信息(字段顺序和原始表的字段顺序一致),并且按照分数降序的方式获取每个班级内的学生的前一名学生姓名(prev_name)、后一名学生姓名(next_name)。

sql 复制代码
mysql> select * from student;
+----+------+-----+--------+----------+
| id | name | age | score  | calss_id |
+----+------+-----+--------+----------+
|  1 | fuck |  18 | 11.000 |        3 |
|  2 | man  |  21 | 33.400 |        1 |
|  3 | yes  |  33 | 91.000 |        3 |
|  4 | NO   |  61 | 71.000 |        2 |
|  5 | bash |  44 | 41.500 |        1 |
|  6 | sql  |  91 | 10.500 |        2 |
|  7 | a    |  38 | 11.000 |        3 |
+----+------+-----+--------+----------+
7 rows in set (0.00 sec)

mysql> select *,lag(name,1) over (partition by calss_id order by score desc) as prev_name,lead(name,1) over (partition by calss_id order by score desc) as next_name from student;
+----+------+-----+--------+----------+-----------+-----------+
| id | name | age | score  | calss_id | prev_name | next_name |
+----+------+-----+--------+----------+-----------+-----------+
|  5 | bash |  44 | 41.500 |        1 | NULL      | man       |
|  2 | man  |  21 | 33.400 |        1 | bash      | NULL      |
|  4 | NO   |  61 | 71.000 |        2 | NULL      | sql       |
|  6 | sql  |  91 | 10.500 |        2 | NO        | NULL      |
|  3 | yes  |  33 | 91.000 |        3 | NULL      | fuck      |
|  1 | fuck |  18 | 11.000 |        3 | yes       | a         |
|  7 | a    |  38 | 11.000 |        3 | fuck      | NULL      |
+----+------+-----+--------+----------+-----------+-----------+
7 rows in set (0.01 sec)
相关推荐
vvvae12347 小时前
分布式数据库
数据库
雪域迷影7 小时前
PostgreSQL Docker Error – 5432: 地址已被占用
数据库·docker·postgresql
bug菌¹8 小时前
滚雪球学Oracle[4.2讲]:PL/SQL基础语法
数据库·oracle
逸巽散人8 小时前
SQL基础教程
数据库·sql·oracle
月空MoonSky9 小时前
Oracle中TRUNC()函数详解
数据库·sql·oracle
momo小菜pa9 小时前
【MySQL 06】表的增删查改
数据库·mysql
向上的车轮10 小时前
Django学习笔记二:数据库操作详解
数据库·django
编程老船长10 小时前
第26章 Java操作Mongodb实现数据持久化
数据库·后端·mongodb
全栈师10 小时前
SQL Server中关于个性化需求批量删除表的做法
数据库·oracle
Data 31711 小时前
Hive数仓操作(十七)
大数据·数据库·数据仓库·hive·hadoop