SQL高级处理

窗口函数

定义:

窗口函数,也叫OLAP函数(Online Anallytical Processing,联机分析处理),可以对数据库数据进行实时分析处理。

基本如法如下:

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

虽然窗口函数有group by 和 order by 的功能,我们看一下两者的区别:

我们看一下之前的数据,如下:

在这里插入图片描述

  1. 不使用窗口函数
select 班级,count(姓名) 
from student 
group by 班级 
order by 班级;

结果:

在这里插入图片描述

  1. 使用窗口函数
select 班级,count(姓名) 
over (partition by 班级 order by 班级) 
as current_count 
from student;

结果:

在这里插入图片描述

可以看到,使用窗口函数不会改变原有表的行数。

这里的窗口是 partition by 分组后的数据叫做窗口,表示“范围”的意思。

窗口函数种类

<窗口函数>可以放下列函数:

  • 专用窗口函数,有rank, dense_rank, row_number等专用窗口函数。
  • 聚合函数,如sum. avg, count, max, min等。

专用窗口函数

rank 函数

计算排序时,如果存在相同位次的记录,则会跳过之后的位次。

例)有 3 条记录排在第 1 位时:1 位、1 位、1 位、4 位……

dense_rank函数

同样是计算排序,即使存在相同位次的记录,也不会跳过之后的位次。

例)有 3 条记录排在第 1 位时:1 位、1 位、1 位、2 位……

row_number函数
赋予唯一的连续位次。

例)有 3 条记录排在第 1 位时:1 位、2 位、3 位、4 位

我们以上面的数据来看三个函数的区别:
为了加以区分,将李二同学的成绩修改成86,如下:

update student
set 成绩=86
where 姓名="李二";
select 姓名, 成绩 ,rank() over (order by 成绩 desc) as ranking
            ,dense_rank() over (order by 成绩 desc) as dense_ranking
            ,row_number() over (order by 成绩 desc) as row_num
from student;

结果:

在这里插入图片描述

我们看到,rank、dense_rank、row_number函数区分是非常明显的,和上面的描述一致。

需要注意的是,这三个专用窗口函数的括号空着就行。

聚合函数

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

select 姓名, 班级, 成绩 ,sum(成绩) over (order by 班级) as sum
            ,max(成绩) over (order by 班级) as max
            ,min(成绩) over (order by 班级) as min
            ,avg(成绩) over (order by 班级) as avg
            ,count(成绩) over (order by 班级) as count
from student;

结果:

在这里插入图片描述

会发现聚合函数是当前所在行及之前所有的行进行聚合,并不是单独的进行聚合。

这样可以看到每一行的数据里直观的看到,截止到本行数据,统计数据是多少。

窗口函数的的应用 - 计算移动平均

preceding(“之前”), 将框架指定为 “截止到之前 n 行”,加上自身行

following(“之后”), 将框架指定为 “截止到之后 n 行”,加上自身行

between 1 preceding and 1 following,将框架指定为 “之前1行” + “之后1行” + “自身”

select 姓名, 班级, 成绩
       ,avg(成绩) over (order by 班级 rows 2 preceding) as avg1
       ,avg(成绩) over (order by 班级 rows between 1 preceding and 1 following) as avg2
from student;

结果:

在这里插入图片描述

其中

avg1计算如下:

  • 该行的数据加上前2行的数据进行求均值,如果前面的行没有数据,不会进行计算,分母也不参与个数。

avg2计算如下:

  • 该行的数据加上前1行的数据和后一行的数据进行求均值,如果前面的行或者后面的行没有数据,不会进行计算,分母也不参与个数。

GROUPING运算符

常规的 group by 只能得到每个分类的小计,有时候还需要计算分类的合计,可以用 with rollup关键字。

select 班级, avg(成绩)
from student
group by 班级
with rollup; 

结果:

在这里插入图片描述

可以看出新的 avg 一列 最后多了一行,再进行求均值。


思考题

① 窗口函数不指定PARTITION BY的效果是什么?
  省略就是不指定分组,这样就失去了窗口函数的意义。

② 为什么说窗口函数只能在 SELECT 子句中使用?实际上,在 ORDER BY 子句使用系统并不会报错。
  因为窗口函数是对 where 或者 group by 子句处理后的结果进行操作,所以窗口函数应该用在select语句中。

おすすめ

転載: blog.csdn.net/lhrfighting/article/details/120462668