0


【SQL应知应会】分析函数的点点滴滴(三)

请添加图片描述

欢迎来到爱书不爱输的程序猿的博客, 本博客致力于知识分享,与更多的人进行学习交流

本文收录于SQL应知应会专栏,本专栏主要用于记录对于数据库的一些学习,有基础也有进阶,有MySQL也有Oracle

请添加图片描述

分析函数的点点滴滴

本篇文章依然是讲SQL的分析函数的知识点,在前面的两篇文章中已经讲解了分析函数是什么、统计分析函数和排序分析函数也进行了详细的讲解和代码演示、开窗函数,这篇文章,将重心放在开窗函数与聚合函数的联合使用,并讲解了偏移分析函数

lag()

lead()

的用法和代码演示,在文章的末尾,对

row_number()

进行了扩展,因为MySQL5.7中是没有这个函数的,mysql8 版本才支持 over partition by 函数的,那么对于低版本的MySQL我们应该如何应对呢?那就快一起来学习这篇文章吧。
如果有不去的地方,大家可以评论区或者私信我,十分感谢

1.什么是分析函数:

👉:传送门💖分析函数💖

1.1统计分析函数略解

👉:传送门💖统计分析函数💖

1.2.排序分析函数

👉:传送门💖排序分析函数💖

1.3 开窗函数 ROW 与 RANGE

👉:传送门💖开窗函数 ROW 与 RANGE💖

1.4 统计分析函数详解

👉:传送门💖统计分析函数💖

1.5 不使用order by时

👉:传送门💖不使用order by时💖

1.6 开窗函数与聚合函数

先进行聚合函数,再进行开窗函数

select deptno,
       sum(count(empno)) over(order by count(empno) 
       rows between unbounded preceding and current row)
from emp t group by deptno;
  • 1.会先进行聚合函数
select deptno,count(empno) from emp group by deptno order by count(empno)

在MySQL和Oracle中,还可以写成

select deptno,count(empno) cnt from emp group by deptno order by cnt
# 因为order by的执行顺序在select后

但是如果是

having

,则在Oracle中是不可以的

# MySQL:可以
select deptno,count(empno) cnt from emp group by deptno having cnt > 1; -- select先执行,having后执行

# Oracle:不可以
select deptno,count(empno) cnt from emp group by deptno having cnt > 1; -- having先执行,select后执行

# Oracle:可以
select deptno,count(empno) cnt from emp group by deptno having count(empno) > 1; -- oracle的having后面只能跟函数
# ChatGPT:
在 Oracle 中,HAVING 用于对 GROUP BY 结果进行筛选过滤,只有满足筛选条件的组才被返回。
通常情况下,HAVING 后面都是需要对分组后的结果进行聚合统计的函数,例如 SUM()、COUNT()、MAX()、
MIN()、AVG() 等函数,因为这些函数能够对每个分组内的数据进行计算,并返回分组后的统计结果。但是,
HAVING 后面也可以跟普通的表达式和逻辑运算符组成的条件,这时需要将这些条件中所涉及的列都包含在 
GROUP BY 子句中。但是在这种情况下,需要注意你的查询结果是否符合你的预期,因为这种方法可能会
导致某些行被排除在分组结果之外。

请添加图片描述

  • 2.再进行开窗函数 - 下图中的结果就是在上图中的结果的基础上进行计算,3,3+6=9,9+6=15
# 开窗函数里面的内容,需要在聚合函数得到的结果的基础上进行
# 如聚合函数中只有deptno和count(empno)
select deptno,
       sum(count(empno)) over(order by count(empno) 
       rows between unbounded preceding and current row)
from emp t group by deptno;

在这里插入图片描述

2. 偏移分析函数 lag()与lead()用法

lag()

lead()

函数是跟偏移量相关的两个分析函数,通过这两个函数可以在一次查询中取出同一字段的**前N行的数据(lag)后N行的数据(lead)**作为独立的列,从而更方便地进行进行数据过滤。

over()

表示 lag()与lead()操作的数据都在over()的范围内,他里面可以使用

partition by

语句(用于分组)

order by

语句(用于排序)

lead(field, num, defaultvalue)

field

需要查找的字段,

num

往后查找的num行的数据,

defaultvalue

没有符合条件的默认值

  • lag() 的使用示例
select e.*,lag(sal) over() from emp e;
# 由下图,显然lag(sal)中有缺省值,为lag(sal,1,null)
  • 代码效果及重点标注如下图所示:在这里插入图片描述
  • lead() 的使用示例
select e.*,lead(sal,2,null)over()from emp e;
  • 代码效果及重点标注如下图所示:在这里插入图片描述
select e.*,lead(sal,1,null)over(partitionby deptno)from emp e;# 加了分区(分组),所以lead会在组内偏移
  • 代码效果及重点标注如下图所示:在这里插入图片描述
  • MySQL可以在原始数据上还用lag()lead(),Oracle需要在over()中加入内容,如partition byorder by
Oracle:select e.*,lead(sal,1,null) over(order by empno) from emp e;

在这里插入图片描述

Oracle:select e.*,lead(sal,1,null)over(partitionby job orderby sal)from emp e;

在这里插入图片描述

3. mysql低版本怎么实现分组排序:row_number()为例

3.1 原因:mysql8 版本才支持 over partition by 函数

3.2 解决方法:

set @rownum = 0;   -- @rownum自增参数,初始化参数为0
set @cid = '';     -- 初始化动态参数cid为空
select 'sid','cid',score
  from(
      select 'sid',  
               'cid',
                score,
                 case when @cid = 'cid' then @rownum := @rownum + 1
              else @rownum := 1  -- 因为@cid初始化为空,所以第一次循环,@cid ≠ 'cid',所以不执行then,执行else子句
              end rn,
              @cid := 'cid', -- 第一轮循环时将cid的值赋给@cid
      from sc
      order by 'cid',score desc -- cid默认升序,score通过desc降序
      ) a
where rn <= 2;
  • 表内容下图左半部分,代码运行解析下图右半部分在这里插入图片描述请添加图片描述
标签: sql oracle 数据库

本文转载自: https://blog.csdn.net/qq_40332045/article/details/131354212
版权归原作者 爱书不爱输的程序猿 所有, 如有侵权,请联系我们删除。

“【SQL应知应会】分析函数的点点滴滴(三)”的评论:

还没有评论