首页 > 数据库 >窗口函数 oracle_11g

窗口函数 oracle_11g

时间:2023-03-31 23:23:30浏览次数:49  
标签:11g CUS NO TRAN DATE 子句 oracle 窗口 AMT

窗口函数 oracle_11g

数据库中的窗口函数也叫分析函数,顾名思义,窗口函数可用于一些复杂的统计分析计算,另外,窗口函数还具有优越的性能表现,可以节约时间和资源,因此窗口函数经常用于数据仓库和大型报表应用中。

窗口函数的结构

窗口函数由四部分组成,分别是分析函数名、分区子句、排序子句和开窗子句,语法结构为:

分析函数名(参数1,参数2 ...) OVER([分区子句] [排序子句] [开窗子句])

开窗子句
[Rows | Range] BETWEEN <Start expr> AND <End expr> 

<Start expr>   -- [UNBOUNDED PRECEDING |CURRENT ROW |n PRECEDING |n FOLLOWING]
<End expr>     -- [UNBOUNDED FOLLOWING |CURRENT ROW |n PRECEDING |n FOLLOWING]

UNBOUNDED PRECEDING:表示从前面的起点
UNBOUNDED FOLLOWING:表示到后面的终点
CURRENT ROW: 当前行
n PRECEDING: 往前n行数据,加上自身行
n FOLLOWING: 往后n行数据,加上自身行

默认:Rows Between UNBOUNDED PRECEDING and CURRENT ROW

语法注解:

分析函数名:
	Oracle中目前有30个左右的分析函数
	mysql8.0之前不支持,之后支持
	
参数:
	依具体函数而定,参数可以是字段名或表达式
	
OVER:
	标识分析函数的关键字,函数名后面跟上OVER表示这是一个窗口函数
	
分区子句:Partition by  可选  默认将所有数据行作为一个单一的大区
	类似聚合函数的group by,数据按Partition by定义的分区列来分区(组),所有分区列相同的数据行会被分到同一个分区,分区的数据会按分区列进行排序
	
排序子句:order by  可选
	按给定的排序列来对分组的数据行进行排序,每个排序字段后面可以指定升序(ASC)或降序(DESC)。对于存在空值null的排序列,可以使用NULLS FIRST将空值排到最上面或使用NULLS LAST将空值排到最下面
	注:
	排序子句的使用方法跟sql中的order by一样
	开窗函数的order by和sql语句的order by的执行时机
      分析及开窗函数是在整个sql查询结束后再进行的, 即sql语句的order by也会影响分析函数的执行结果,有以下两种情况:
        1) 两者一致,即sql语句中的order by语句与开窗函数的order by一致,则sql语句中的order by先执行,分析函数在分析时就不必再排序
        2) 两者不一致,即sql语句中的order by语句与开窗函数的order by不一致,则分析及开窗函数先分析排序,sql语句中的order by再最后执行

窗口子句: 
	划定分析函数进行计算时的数据子集,这个数据子集对应的窗口可以是动态的滑动窗口,滑动窗口的上下边界依排序后的分区数据集且通过 [Rows | Range] 配合 <Start expr> / <End expr> 的几种关键字指定,其中Rows通过与当前行数的比较来指定物理窗口范围,Range通过与当前行值的比较来指定逻辑窗口范围。如果不显示指定窗口子句,默认为 Rows Between Unbounded Preceding and Current Row 。注意不是所有分析函数都支持窗口子句。
	注:
	无论是否省略分组子句,都有:
      窗口子句(rows)不能单独存在,必须有order by子句时才能出现
      相反,有order by子句,可以没有窗口子句(rows)

  当省略窗口子句时
      如果存在order by,则默认的窗口是unbounded preceding and current row,即当前组的第一行到当前行
      如果不存在order by,则默认的窗口是unbounded preceding and unbounded following,即整个组

常用的分析函数

函数名 描述 是否支持窗口子句
sum 统计给定分区与窗口范围的数据的和 支持
count 统计给定分区与窗口范围的数据的条数,可以配合distinct一起使用,但要注意有些数据库不支持distinct的使用 支持
avg 统计给定分区与窗口范围的数据的均值 支持
max 统计给定分区与窗口范围的数据的最大值 支持
min 统计给定分区与窗口范围的数据的最小值 支持
lag 访问一个分区或结果集中之前的n行,n可由函数的参数指定 不支持
lead 访问一个分区或结果集中之后的n行,n可由函数的参数指定 不支持
first_value 访问一个分区或结果集中的第一行 支持
last_value 访问一个分区或结果集中的最后一行 支持
nth_value 访问一个分区或结果集中的任意一行 支持
row_number 对行进行排序并为每一行增加一个唯一编号 不支持
rank 将数据行值按照排序后的顺序进行排名,在有并列的情况下排名值将被跳过 不支持
dense_rank 将数据行值按照排序后的顺序进行排名,在有并列的情况下也不跳过排名值 不支持
listagg 将来自多行的列值以给定分隔符转化为一行的列表形式 不支持

窗口函数的使用

--建表
create table test1(
  CUS_NO varchar2(10),    --客户编号
  AGE int,                --年龄
  TRAN_MONTH varchar2(6), --交易月份
  TRAN_DATE date,         --交易日期
  TRAN_AMT numeric(20,2)  --交易金额
);
--插入测试数据
insert into test1(CUS_NO,AGE,TRAN_MONTH,TRAN_DATE,TRAN_AMT) values('cus_101028',28,'201910',to_date('20191012', 'YYYYMMDD'),880.00);commit;
insert into test1(CUS_NO,AGE,TRAN_MONTH,TRAN_DATE,TRAN_AMT) values('cus_101028',28,'201910',to_date('20191013', 'YYYYMMDD'),69.00);commit;
insert into test1(CUS_NO,AGE,TRAN_MONTH,TRAN_DATE,TRAN_AMT) values('cus_101028',28,'201910',to_date('20191014', 'YYYYMMDD'),128.00);commit;
insert into test1(CUS_NO,AGE,TRAN_MONTH,TRAN_DATE,TRAN_AMT) values('cus_101028',28,'201910',to_date('20191015', 'YYYYMMDD'),12.00);commit;
insert into test1(CUS_NO,AGE,TRAN_MONTH,TRAN_DATE,TRAN_AMT) values('cus_101028',28,'201910',to_date('20191016', 'YYYYMMDD'),99.00);commit;
insert into test1(CUS_NO,AGE,TRAN_MONTH,TRAN_DATE,TRAN_AMT) values('cus_101028',28,'201910',to_date('20191018', 'YYYYMMDD'),199.00);commit;
insert into test1(CUS_NO,AGE,TRAN_MONTH,TRAN_DATE,TRAN_AMT) values('cus_101028',28,'201910',to_date('20191020', 'YYYYMMDD'),28.00);commit;
insert into test1(CUS_NO,AGE,TRAN_MONTH,TRAN_DATE,TRAN_AMT) values('cus_101028',28,'201911',to_date('20191101', 'YYYYMMDD'),39.00);commit;

insert into test1(CUS_NO,AGE,TRAN_MONTH,TRAN_DATE,TRAN_AMT) values('cus_101029',null,'201910',to_date('20191012', 'YYYYMMDD'),33.00);commit;
insert into test1(CUS_NO,AGE,TRAN_MONTH,TRAN_DATE,TRAN_AMT) values('cus_101029',null,'201910',to_date('20191013', 'YYYYMMDD'),28.00);commit;
insert into test1(CUS_NO,AGE,TRAN_MONTH,TRAN_DATE,TRAN_AMT) values('cus_101029',null,'201910',to_date('20191014', 'YYYYMMDD'),120.00);commit;
insert into test1(CUS_NO,AGE,TRAN_MONTH,TRAN_DATE,TRAN_AMT) values('cus_101029',null,'201910',to_date('20191015', 'YYYYMMDD'),230.00);commit;
insert into test1(CUS_NO,AGE,TRAN_MONTH,TRAN_DATE,TRAN_AMT) values('cus_101029',null,'201910',to_date('20191016', 'YYYYMMDD'),129.00);commit;
insert into test1(CUS_NO,AGE,TRAN_MONTH,TRAN_DATE,TRAN_AMT) values('cus_101029',null,'201911',to_date('20191102', 'YYYYMMDD'),321.00);commit;
insert into test1(CUS_NO,AGE,TRAN_MONTH,TRAN_DATE,TRAN_AMT) values('cus_101029',null,'201911',to_date('20191103', 'YYYYMMDD'),25.00);commit;
insert into test1(CUS_NO,AGE,TRAN_MONTH,TRAN_DATE,TRAN_AMT) values('cus_101029',null,'201911',to_date('20191104', 'YYYYMMDD'),89.00);commit;
insert into test1(CUS_NO,AGE,TRAN_MONTH,TRAN_DATE,TRAN_AMT) values('cus_101029',null,'201911',to_date('20191105', 'YYYYMMDD'),60.00);commit;

insert into test1(CUS_NO,AGE,TRAN_MONTH,TRAN_DATE,TRAN_AMT) values('cus_101030',35,'201910',to_date('20191015', 'YYYYMMDD'),260.00);commit;
insert into test1(CUS_NO,AGE,TRAN_MONTH,TRAN_DATE,TRAN_AMT) values('cus_101030',35,'201910',to_date('20191016', 'YYYYMMDD'),320.00);commit;
insert into test1(CUS_NO,AGE,TRAN_MONTH,TRAN_DATE,TRAN_AMT) values('cus_101030',35,'201910',to_date('20191016', 'YYYYMMDD'),180.00);commit;
insert into test1(CUS_NO,AGE,TRAN_MONTH,TRAN_DATE,TRAN_AMT) values('cus_101030',35,'201910',to_date('20191017', 'YYYYMMDD'),100.00);commit;
insert into test1(CUS_NO,AGE,TRAN_MONTH,TRAN_DATE,TRAN_AMT) values('cus_101030',35,'201910',to_date('20191018', 'YYYYMMDD'),40.00);commit;

分区子句的使用

需求:统计每个客户在保留原来数据行的基础上增加一列统计列(消费总额)

例:

客户编号 年龄 交易月份 交易日期 交易金额 消费总额(追加列) 每个月的消费总额(追加列)

-- 统计每个客户的消费总额
SELECT
	CUS_NO 客户编号,
	AGE 年龄,
	TRAN_MONTH 交易月份,
	TRAN_DATE 交易日期,
	TRAN_AMT 交易金额,
	sum( TRAN_AMT ) over ( PARTITION BY CUS_NO ) AS 消费总额, -- 每个客户的消费总额
	sum( TRAN_AMT ) over ( PARTITION BY CUS_NO, TRAN_MONTH ) AS 每个月的消费总额 -- 每个客户每个月的消费总额
FROM
	test1;

分区子句 partition by CUS_NO 将数据集按每个不同的客户编号来分组,然后汇总交易金额即可得到每个客户的消费总额

未指定排序子句会使用分区列(CUS_NO)作为排序字段

未指定窗口子句会使用Rows Between Unbounded Preceding and Current Row

排序子句的使用

需求:统计每个客户逐日累计的消费金额

例:

2019-10-15当日消费金额 = 0+当日

2019-10-16当日消费金额 = 2019-10-15当日消费金额 + 当日

2019-10-17当日消费金额 = 2019-10-16当日消费金额 + 当日

以此类推。

-- 统计每个客户逐日累计的消费金额 
SELECT
CUS_NO 客户编号,
AGE 年龄,
TRAN_MONTH 交易月份,
TRAN_DATE 交易日期,
TRAN_AMT 交易金额,
sum( TRAN_AMT ) over ( PARTITION BY CUS_NO ORDER BY TRAN_DATE ) AS 逐日累计消费金额 
FROM
	test1;

分区子句 partition by CUS_NO 将数据集按每个不同的客户编号来分组

排序子句 order by TRAN_DATE 中,按交易日期正序排序

未指定窗口子句会使用Rows Between Unbounded Preceding and Current Row

窗口子句的使用

需求:统计每个客户每个交易日期及其前后一天的消费总额

例:

日期 2019-10-15、2019-10-16、2019-10-17

2019-10-15 消费总额 = 0 + 2019-10-15 消费总额 + 2019-10-16 消费总额

2019-10-16 消费总额 = 2019-10-15 消费总额 + 2019-10-16 消费总额 + 2019-10-17 消费总额

2019-10-17 消费总额 = 2019-10-16 消费总额 + 2019-10-17 消费总额 + 2019-10-18 消费总额

以此类推。

-- 统计每个客户每个交易日期及其前后一天的消费总额
SELECT
	CUS_NO 客户编号,
	AGE 年龄,
	TRAN_MONTH 交易月份,
	TRAN_DATE 交易日期,
	TRAN_AMT 交易金额,
	-- Range 通过与当前行值的比较来指定逻辑窗口范围    统计每个客户每个交易日期及其前后一天的消费总额  
	sum( TRAN_AMT ) over ( PARTITION BY CUS_NO ORDER BY TRAN_DATE RANGE BETWEEN 1 preceding AND 1 following ) AS range消费总额,
	-- Rows 通过与当前行数的比较指定物理窗口范围    统计每个客户每个交易日期及其前后一条的消费总额
	sum( TRAN_AMT ) over ( PARTITION BY CUS_NO ORDER BY TRAN_DATE rows BETWEEN 1 preceding AND 1 following ) AS rows消费总额 
FROM
	test1;

分区子句 partition by CUS_NO 将数据集按每个不同的客户编号来分组

排序子句 order by TRAN_DATE 中,按交易日期正序排序

窗口子句

range between 1 preceding and 1 following 表示滑动窗口为当前行的日期以及这个日期减去1天和加上1天对应的这个日期范围内的消费金额加总

rows BETWEEN 1 preceding AND 1 following 表示滑动窗口为当前行的日期以及这个日期上面一行的容器和下面一行的日期的消费金额加总

标签:11g,CUS,NO,TRAN,DATE,子句,oracle,窗口,AMT
From: https://www.cnblogs.com/fuqian/p/17277811.html

相关文章

  • selenium之关闭窗口,指定窗口大小,前进,后退,刷新等操作
    关闭窗口1、仅关闭当前窗口(Tab页),其他窗口不退出关闭用户当前正在使用的Web浏览器窗口,即WebDriver当前正在访问的窗口。.close()方法既不需要任何参数,也无任何返回值。driver.close()相当于浏览器中每个Tab页中的叉叉。2、关闭所有的浏览器窗口(WebDriver初始化的整个浏览器进程)同于......
  • oracle静默安装
    ##################       如何确定安装的oracle是否有问题?              #####################......
  • 对于11g新特性自适应游标共享
    绑定变量优缺点、使用、绑定变量窥探、Oracle自适应共享游标_ITPUB博客自适应游标共享虽然解决了一些由于10g中绑定变量窥探只进行首次硬解析才窥探生成执行计划,由于数据倾斜造成执行计划不准确问题,但是不是每次执行sql都进行窥探,游标共享是“自适应”的,也会出现执行计划不准确......
  • 获取浏览器窗口尺寸及监听浏览器变化
    原JS获取:窗口可视高度:window.innerWidth窗口可视宽度:window.innerHeight窗口文档高度:document.body.clientWidth窗口文档宽度:document.body.clientHeightJQuery获取:窗口可视高度:$(window).height()窗口文档高度:$(window).height()窗口body高度:$(document.body).height()窗口文......
  • oracle的各版本的名称
    我最早接触的是oracle的版本8那个时候是8ii是internet后来是9i然后到10,就是版本10gg是grid的意思然后是11g然后12就变成了C,就是12cc是cloud的意思然后后面的版本是18c19c21c现在23c还处于研发阶段现在主推的版本是19c————————————————版权声明:本文为CSDN博主......
  • oracle 禁用job任务
    参考(17条消息)Oracle11g自带的系统Job介绍_oracle11gjob_shayuwei的博客-CSDN博客SQL>selectjob_namefromdba_scheduler_jobs;SQL>setlin160SQL>colownerfora10SQL>colDIRECTORY_NAMEfora25SQL>colDIRECTORY_PATHfora50SQL>select*fromd......
  • CAD命令行怎么恢复到初始状态?CAD命令行窗口恢复步骤
    CAD制图过程中,为了提高绘图效率经常会用到各种命令,很多命令信息及操作提示会在CAD命令行中显示。可当不小心改变了命令行的状态时,该怎么办呢?下面就和小编来了解一下CAD命令行怎么恢复到初始状态吧!CAD命令行窗口恢复初始步骤:1、启动浩辰CAD软件后,调用OP命令,即可打开【选项】对话......
  • oracle锁表
    1.查询引起了锁表的原因SELECTl.session_idsid,s.serial#,l.locked_mode,l.oracle_username,s.user#,l.os_user_name,s.machine,s.terminal,a.sql_text,a.actionFROMv$sqlareaa,v$sessions,v......
  • oracle 查看表空间实际占用情况
    SELECTtablespace_name表空间名,round(SUM(bytes)/1000/1000/1000,2)alloc_bytes,round(SUM(maxbytes)/1000/1000/1000,2)maxbytesFROMdba_data_filesGROUPBYtablespace_name;SELECTtablespace_nam......
  • oracle 优化监控相关
    SELECTsn.username,m.SID,sn.SERIAL#,m.TYPE,DECODE(m.lmode,0,'None',1,'Null',2,'RowShare',3,'RowExcl.',4,......