首页 > 数据库 >Oracle 分析函数

Oracle 分析函数

时间:2023-04-14 14:13:49浏览次数:35  
标签:分析 salary 函数 sum u1 id Oracle order

说明:由于 oracle 默认大写,所以在本文中会出现一下大写一下小写,在 oracle 都可以执行,如果 oracle 字段为小写字段,则需要用双引号查询。

需求举例

需求

假如存在一个需求,查询每个用户所在部门的总工资,在每个员工后面增加一个总工资字段显示。

img

例如部门一合计为15000,部门二合计为10000,需要显示如下

img

模拟数据

我们先创建一下数据:

-- 创建测试表
CREATE TABLE user_info_test(
    id varchar2(32) PRIMARY KEY,
    name varchar2(32),
    dept varchar2(32),
    salary number(10,4)
);

-- 批量插入数据
INSERT INTO user_info_test(id,name,dept,salary)
(SELECT '1','员工一','部门一',3000 FROM dual UNION ALL 
 SELECT '2','员工二','部门一',4000 FROM dual UNION all
 SELECT '3','员工三','部门一',8000 FROM dual UNION all
 SELECT '4','员工四','部门二',10000 FROM dual);

实现

如果要实现以上需求,常规做法为:

  • 先查询出每个部门的工资合计
  • 再与原表拼接(根据 dept 部门拼接)
-- 查询每个部门的工资合计
SELECT sum(SALARY) sum_salary,dept FROM USER_INFO_TEST u2 GROUP BY dept;

-- 与原表拼接
SELECT u1.*,u3.sum_salary 
FROM USER_INFO_TEST u1 
INNER JOIN (SELECT sum(SALARY) sum_salary,dept FROM USER_INFO_TEST u2 GROUP BY dept) u3
ON u1.dept = u3.dept
ORDER BY u1.ID;

分析函数

但是上面的写法过于冗余,可以利用 oracle 特有函数,分析函数(窗口函数/开窗函数)。

说明

分析函数可以在数据中进行分组然后计算基于组的某种统计值,并且每一组的每一行都可以返回一个统计值

格式

函数 over([partition by 分组字段] [order by 排序字段 [rows 窗口]])

注:[] 为可填,并非必填

  • 函数可以分为
    • 聚合函数,例如 sum(),max(),min() ...
    • 排序函数,例如 row_number(),rank() ...
  • partition by
    • 可以看成是 group by,对前面的聚合函数进行分组计算
      • 例如 sum(salary) over(partition by dept) 就是根据 dept 进行分组,求出每个分组中的 sum(salary)
    • 当 partition by 不写时,则为整个列表看成是一个分组
  • order by 比较麻烦,具体看后面 order by。
  • rows 窗口分为
    • UNBOUNDED PRECEDING 第一行
    • CURRENT ROW 当前行
    • UNBOUNDED FOLLOWING 最后一行

实现上述需求

利用窗口函数实现需求,由于我们需要求和,所以需要使用 聚合函数sum,同时对 dept 进行分组

-- 分析函数/窗口函数
sum(salary) over(partition by dept);

-- 整个函数
SELECT u1.*,
sum(SALARY) over(PARTITION BY u1.DEPT) sum_salary 
FROM USER_INFO_TEST u1
ORDER BY u1.ID

计算总工资合计,但是通过 over() 进行分析,通过 dept 字段进行分组合计,所以只会求出自己所在部门的 salary 合计。

img

再如我们需要查询出本部门最低、最高的 salary 在后面进行显示对比

SELECT u1.*,
sum(SALARY) over(PARTITION BY u1.DEPT) sum_salary,
min(SALARY) over(PARTITION BY u1.DEPT) min_salary,
max(SALARY) over(PARTITION BY u1.DEPT) max_salary
FROM USER_INFO_TEST u1
ORDER BY u1.ID;

img

谈谈 order by

分析函数主要是用于将聚合函数等转换成单行函数,方便后续修改或者查看等操作。

函数主要使用聚合函数,通过 partition by 分组字段进行分组,等同于 group by。

要注意 order by 并不是普通排序,既然是某个分组聚合,肯定内部不存在内排序,我们来试一下采用 order by。

SELECT u1.*,
sum(SALARY) over(PARTITION BY u1.DEPT) sum_salary,
sum(SALARY) over(PARTITION BY u1.DEPT ORDER BY id) order_salary
FROM USER_INFO_TEST u1
ORDER BY u1.ID;

img

可以看到加了 order by 之后,order_salary 首先是在部门内部进行了合计,但是是从上到下,在部门内部进行合计,是根据 id 从小到大在 dept 内部进行合计(order by id)。

id 为 2 的 order_salary 为 (id 为 1 的 salary + id 为 2 的 salary);

id 为 3 的 order_salary 为 (id 为 1 的 salary + id 为 2 的 salary + id 为 3 的 salary);

id 为 4 的 order_slary 为 自己的 salary(因为他是部门二,不属于部门一)

rows 窗口

在了解了分析函数的 order by 之后,rows 相对而言属于比较简单。

注意 rows 不能单独使用,必须和 order by 结合使用,order by 默认 rows between UNBOUNDED PRECEDING and CURRENT ROW ,即从第一行到当前行,所以上方合计就是从 id 小的到当前行合计。

SELECT u1.*,
sum(SALARY) over(PARTITION BY u1.DEPT) sum_salary,
sum(SALARY) over(PARTITION BY u1.DEPT ORDER BY id) order_salary,
sum(SALARY) over(PARTITION BY u1.DEPT ORDER BY id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) order_salary2
FROM USER_INFO_TEST u1
ORDER BY u1.ID;

img

一般用的 rows 比较少,大致了解就行。

再谈分析函数

分析函数主要用于将聚合函数变成单行函数去执行计算等操作,注意由于 select 字段是在 sql 中最后执行的,所以分析函数也同样会用到查询中的 where 条件,所以不用担心他只会进行分组。

不使用分析函数也可以通过其他方法查询数据,分析函数只是一种辅助功能,方便编写 sql。

标签:分析,salary,函数,sum,u1,id,Oracle,order
From: https://www.cnblogs.com/ytryhard/p/17318114.html

相关文章

  • Service Mesh框架选型对比分析:Linkerd、Envoy、Istio、Conduit
    当前,业界主要有以下主要几种ServiceMesh框架,下面进行详细的说明及对比。1、LinkerdLinkerd是Buoyant公司2016年率先开源的高性能网络代理,是业界的第一款ServiceMesh框架。其主要用于解决分布式环境中服务之间通信面临的一些问题,如网络不可靠、不安全、延迟丢包等问题。Linkerd使......
  • 国网B接口调阅实时视频规范解读和代码示例分析
    接口描述国网B接口调阅实时视频,相关规范写的比较粗略:调阅实时视频包括信令接口和媒体流接口,采用标准的SIPINVITE+SDP流程,媒体传输使用RTP/RTCP。SDP中RTPPayload的取值应遵守下面接口参数中的定义:a)SDP中的媒体信息,应仅有一个m行,用于描述视频格式。b)视频数据用RTP打包传......
  • ADVMP 三代壳(vmp加固)原理分析(执行流程)
    由于在加壳时插入了System.loadLibrary("advmp");,看一下JNI_OnLoadJNIEXPORTjintJNICALLJNI_OnLoad(JavaVM*vm,void*reserved){JNIEnv*env=NULL;if(vm->GetEnv((void**)&env,JNI_VERSION_1_4)!=JNI_OK){returnJNI_ERR;}......
  • mybatis 连接 ORACLE
     application-common-dev.ymlspring:profiles:include:[common]main:allow-bean-definition-overriding:true#Redis服务器IPredis:host:127.0.0.1#Redis服务器连接端口port:6379#Redis服务器连接密码password:testj......
  • ADVMP 三代壳(vmp加固)原理分析(加壳流程)
    开源项目地址https://github.com/chago/ADVMPvmp加固可以说时各大加固厂商的拳头产品了,这个开源项目虽然不是十分完善,让我们可以一览vmp加固的原理,是十分好的学习资源vmp全称:virtualmachineprotect,本质是将原来smali对应的代码转化为自定义的代码,然后通过自定义的......
  • C++的引用变量作为函数参数
    一、问题引入在C++的中新增一个特性:按引用传递变量,虽然与按传递变量的地址可以实现相同的结果,但引用有其独特的地方。引用传递:引用经常被用作函数参数,使得函数中的变量名成为调用程序中的变量的别名。通过引用变量用作参数,函数将使用原始数据,而不是其副本。二、解决过程举......
  • Oracle - 'yyyy-mm-dd' & 'yyyymmdd'
     oracle中日期格式'yyyy-mm-dd'和'yyyymmdd'的区别 对于年月日中"日"是个位的情况下,处理不一样,'yyyymmdd'格式没问题,而式'yyyy-mm-dd'格式则不行,请看: SQL>altersessionsetnls_date_format='yyyy-mm-ddhh24:mi:ss'; Sessionaltered. SQL>......
  • C语言函数大全--g开头的函数(下)
    C语言函数大全本篇介绍C语言函数大全--g开头的函数(下)17.getmodename17.1函数说明函数声明函数功能char*getmodename(intmode_name);获取指定的图形模式名17.2演示示例#include<graphics.h>#include<stdlib.h>#include<stdio.h>intmain(void){......
  • Postman接口测试之当多个接口都需要使用自定义的函数时解决方案
    //自定义时间戳的动态参数//vartimes=Date.now()//pm.globals.set("times",times);//需要随机出一个范围内的整数数,函数//constrandomInt=(min,max)=>Math.floor(Math.random()*(max-min+1))+min//pm.globals.set("randomNumber",randomInt(1000,3000));......
  • ajax使用回调函数的例子(原生代码和jquery代码)
    ajax使用回调函数的例子(原生代码和jquery代码)一、 ajax代码存在的问题(异步交互的问题)ajax所请求的url,如果因为网络等问题,很久没有回应,则给用户造成“假死”的现象。代码如下:xmlHttp=GetXmlHttpObject();xmlHttp.open();xmlHttp.send();//下面这句,会一直等待,直到有返回值......