MySQL 8.0之窗口函数

文章目录

  • 简介
  • 如何使用?
    • 1. rank() 专用窗口函数
    • 2. 其他专业窗口函数
    • 3. 聚合函数作为窗口函数

简介

原文链接:https://zhuanlan.zhihu.com/p/92654574

此部分官方文档:https://dev.mysql.com/doc/refman/8.0/en/window-function-descriptions.html

注意:从版本8.0开始,MySQL支持窗口函数。窗口函数允许您以新的,更简单的方式解决查询问题,并具有更好的性能。

窗口函数的基本语法如下:

<窗口函数> over (partition by <用于分组的列名>
                order by <用于排序的列名>)

<窗口函数>的位置,可以放以下两种函数:

  • 1) 专用窗口函数,包括后面要讲到的rank, dense_rank, row_number等专用窗口函数。
  • 2) 聚合函数,如sum. avg, count, max, min等

如何使用?

1. rank() 专用窗口函数

例如下图,是班级表中的内容:
MySQL 8.0之窗口函数_第1张图片
如果我们想在每个班级内按成绩排名,得到下面的结果:
MySQL 8.0之窗口函数_第2张图片
以班级“1”为例,这个班级的成绩“95”排在第1位,这个班级的“83”排在第4位。上面这个结果确实按我们的要求在每个班级内,按成绩排名了。

得到上面结果的sql语句代码如下:

select *,rank() over (partition by 班级
                 order by 成绩 desc) as ranking
from 班级表

我们来解释下这个sql语句里的select子句。rank是排序的函数。要求是“每个班级内按成绩排名”,这句话可以分为两部分:

  • 1)每个班级内:按班级分组
    partition by用来对表分组。在这个例子中,所以我们指定了按“班级”分组(partition by 班级)
  • 2)按成绩排名
    order by子句的功能是对分组后的结果进行排序,默认是按照升序(asc)排列。在本例中(order by 成绩 desc)是按成绩这一列排序,加了desc关键词表示降序排列。

通过下图,我们就可以理解partiition by(分组)和order by(在组内排序)的作用了。
MySQL 8.0之窗口函数_第3张图片

窗口函数具备了我们之前学过的group by子句分组的功能和order by子句排序的功能。那么,为什么还要用窗口函数呢?

这是因为,group by分组汇总后改变了表的行数,一行只有一个类别。而partiition by和rank函数不会减少原表中的行数。 例如下面统计每个班级的人数。
MySQL 8.0之窗口函数_第4张图片
现在我们说回来,为什么叫“窗口”函数呢?这是因为partition by分组后的结果称为“窗口”,这里的窗口不是我们家里的门窗,而是表示“范围”的意思。

简单来说,窗口函数有以下功能:

  • 1)同时具有分组和排序的功能
  • 2)不减少原表的行数
  • 3)语法如下:
<窗口函数> over (partition by <用于分组的列名>
                order by <用于排序的列名>)

2. 其他专业窗口函数

官方文档:https://dev.mysql.com/doc/refman/8.0/en/window-function-descriptions.html

注意:专用窗口函数rank, dense_rank, row_number有什么区别呢?

它们的区别我举个例子,你们一下就能看懂:

select *,
   rank() over (order by 成绩 desc) as ranking,
   dense_rank() over (order by 成绩 desc) as dese_rank,
   row_number() over (order by 成绩 desc) as row_num
from 班级表

得到结果:
MySQL 8.0之窗口函数_第5张图片
从上面的结果可以看出:

  1. rank函数:这个例子中是5位,5位,5位,8位,也就是如果有并列名次的行,会占用下一名次的位置。比如正常排名是1,2,3,4,但是现在前3名是并列的名次,结果是:1,1,1,4。

  2. dense_rank函数:这个例子中是5位,5位,5位,6位,也就是如果有并列名次的行,不占用下一名次的位置。比如正常排名是1,2,3,4,但是现在前3名是并列的名次,结果是:1,1,1,2。

  3. row_number函数:这个例子中是5位,6位,7位,8位,也就是不考虑并列名次的情况。比如前3名是并列的名次,排名是正常的1,2,3,4。

这三个函数的区别如下:
MySQL 8.0之窗口函数_第6张图片
最后,需要强调的一点是:在上述的这三个专用窗口函数中,函数后面的括号不需要任何参数,保持()空着就可以。

3. 聚合函数作为窗口函数

聚和窗口函数和上面提到的专用窗口函数用法完全相同,只需要把聚合函数写在窗口函数的位置即可,但是函数后面括号里面不能为空,需要指定聚合的列名。

我们来看一下窗口函数是聚合函数时,会出来什么结果:

select *,
   sum(成绩) over (order by 学号) as current_sum,
   avg(成绩) over (order by 学号) as current_avg,
   count(成绩) over (order by 学号) as current_count,
   max(成绩) over (order by 学号) as current_max,
   min(成绩) over (order by 学号) as current_min
from 班级表

得到结果:
MySQL 8.0之窗口函数_第7张图片

你可能感兴趣的:(Mysql,mysql,sql,数据库)