ocp考试资料群:569933648 验证码:ocp OCP 12c 19c考试题库解析与资料群:钉钉群号:35277291
全部博文(487)
分类: Mysql/postgreSQL
2023-08-11 15:51:10
PostgreSQL从小白到专家,是从入门逐渐能力提升的一个系列教程,内容包括对PG基础的认知、包括安装使用、包括角色权限、包括维护管理、、等内容,希望对热爱PG、学习PG的同学们有帮助,欢迎持续关注CUUG PG技术大讲堂。
第25讲:窗口函数
内容1 : 窗口函数如何定义
内容2 : 专用窗口函数的种类
内容3 : 掌握常用的窗口函数
内容4 : 熟练使用聚合函数作为窗口函数
内容5 : 窗口函数的框架来计算移动平均
“窗口”的由来
窗口函数也称为 OLAP 函数。为了让大家快速形成直观印象,才起了这样一个容易理解的名称。
通过 PARTITION BY 分组后的记录集合称为“窗口”。
从词语意思的角度考虑,可能“组”比“窗口”更合适一些,但是在SQL中,“组”更多的是用来特指使用 GROUP BY 分割后的记录集合,因此,为了避免混淆,使用PARTITION BY 时称为窗口。
注意:可以不指定 PARTITION BY ,会将这个表当成一个“大窗口”。
窗口函数应用场景
应用场景:
(1)用于分区排序
(2)动态Group By
(3)Top N
(4)累计计算
(5)层次查询
窗口函数的种类
窗口函数大体可以分为以下两种:
1、能够作为窗口函数的聚合函数(SUM、AVG、COUNT、MAX、MIN)。
2、RANK、DENSE_RANK、ROW_NUMBER 等专用窗口函数。
上面{BANNED}中国第一种应用中将聚合函数书写在语法的“< 窗口函数 >”中,就能够当作窗口函数来使用了。聚合函数根据使用语法的不同,可以在聚合函数和窗口函数之间进行转换。
上面第二种应用中的函数是标准 SQL 定义的 OLAP 专用函数,这里将其统称为“专用窗口函数”。从这些函数的名称可以很容易看出其 OLAP 的用途。
专用窗口函数
RANK 函数
计算排序时,如果存在相同位次的记录,则会跳过之后的位次。
比如:有 3 条记录排在第 1 位时:1 位、1 位、1 位、4 位……
ROW_NUMBER 函数
赋予唯一的连续位次。
比如:有 3 条记录排在第 1 位时:1 位、2 位、3 位、4 位……
DENSE_RANK 函数
同样是计算排序,即使存在相同位次的记录,也不会跳过之后的位次。
比如:有 3 条记录排在第 1 位时:1 位、1 位、1 位、2 位……
RANK()函数
--示例:
select ename,job,sal, rank() over (PARTITION BY job ORDER BY sal) as rankin from emp;
PARTITION BY 能够设定分组和排序的对象范围。本例中,为了按照工作进行分组和排序,我们指定了job。
ORDER BY 能够指定按照哪一列、何种顺序进行排序。为了按照工资的升序进行排列,我们指定了sal 。
DENSE_RANK()函数
--示例
select ename,job,sal,DENSE_RANK() over (PARTITION by job ORDER BY SAL ) as dense_rankin from emp;
ROW_NUMBER 函数
--示例:
select ename,job,sal,ROW_NUMBER() over (PARTITION BY job ORDER BY SAL ) as unique_rankin from emp;
专用窗口函数使用技巧
使用 RANK 或 ROW_ NUMBER 时无需任何参数,只需要像 RANK ()或者 ROW_ NUMBER() 这样保持括号中为空就可以了。这也是专用窗口函数通常的使用方式。
select ename,job,sal, RANK() OVER (PARTITION BY job ORDER BY sal) as rankin, DENSE_RANK() OVER (PARTITION BY job ORDER BY sal) as dense_rank, ROW_NUMBER() OVER (PARTITION BY job ORDER BY sal) as row_rankinfrom emp;
窗口函数的适用范围
使用窗口函数的位置却有非常大的限制。更确切地说,窗口函数只能书写在一个特定的位置。这个位置就是 SELECT 子句之中。反过来说,就是这类函数不能在WHERE 子句或者 GROUP BY 子句中使用。
为什么窗口函数只能在 SELECT 子句中使用呢?
在 DBMS内部,窗口函数是对 WHERE 子句或者 GROUP BY 子句处理后的“结果”进行的操作。大家仔细想一想就会明白,在得到用户想要的结果之前,即使进行了排序处理,结果也是错误的。在得到排序结果之后,如果通过 WHERE 子句中的条件除去了某些记录,或者使用 GROUP BY 子句进行了汇总处理,那好不容易得到的排序结果也无法使用了。
作为窗口函数使用的聚合函数
--计算price值的累计结果
select name,price, SUM(price) over (order by name) as current_sumfrom product;
--计算SAL值的累计结果
select ename,sal,SUM(sal) over (ORDER BY ename) as current_sumfrom emp;
所有的聚合函数都能用作窗口函数,其语法和专用窗口函数完全相同。
使用 SUM 函数时,并不像 RANK 或者 ROW _ NUMBER 那样括号中的内容为空,而是和之前我们学过的一样,需要在括号内指定作为汇总对象的列。
指定框架(汇总范围)
select name,price,avg (price) over (order by name rows 2 preceding) as moving_avg from product;
这里我们使用了 ROWS (“行”)和 PRECEDING (“之前”)两个关键字,将框架指定为“截止到之前 ~ 行”,因此“ ROWS 2 PRECEDING ”就是将框架指定为“截止到之前 2 行”,也就是将作为汇总对象的记录限定为如下的“{BANNED}最佳靠近的 3 行”。
{BANNED}最佳靠近的3行=自身(当前记录)+ 之前第1行的记录 + 之前第2行的记录
计算移动平均
由于框架是根据当前记录来确定的,因此和固定的窗口不同,其范围会随着当前记录的变化而变化。
这样的统计方法称为移动平均(moving average)。由于这种方法在希望实时把握“{BANNED}最佳近状态”时非常方便,因此常常会应用在对股市趋势的实时跟踪当中。
使用关键字 FOLLOWING (“之后”)替换 PRECEDING ,就可以指定“截止到之后 ~ 行”作为框架了。
计算移动平均—同时指定前后行
select name,price,avg (price) over (order by name rows between 1 preceding and 1 following) as moving_avgfrom product;
两个order by
OVER 子句中的 ORDER BY 只是用来决定窗口函数按照什么样的顺序进行计算的,对结果的排列顺序并没有影响。在 SELECT 语句的{BANNED}最佳后,使用 ORDER BY子句进行指定按照 ranking 列进行排列,结果才会顺序显示,但是如果使用了,会打乱原本窗口函数出来的显示结果。
有些 DBMS(PG) 也可以按照窗口函数的 ORDER BY 子句所指定的顺序对结果进行排序。
在一条 SELECT 语句中使用两次 ORDER BY 会有点别扭,但是尽管这两个 ORDER BY 看上去是相同的,但其实它们的功能却完全不同。
总结
专用窗口函数 rank()
row_number()
dense_ranking()。
将聚合函数作为窗口函数使用---需要带参数
框架的用法---计算移动平均
以上就是【PostgreSQL从小白到专家】第25讲 - 窗口函数 的内容,欢迎一起探讨交流钉钉交流群:35,82,24,60,往期视频及文档内容联系: CUUG