oracle之分析函数over及开窗函数
Oracle中分析函数用法小结
Oracle中分析函数用法小结一.分析函数适用场景:○1需要对同样的数据进行不同级别的聚合操作○2需要在表内将多条数据和同一条数据进行多次的比较○3需要在排序完的结果集上进行额外的过滤操作二.分析函数语法:FUNCTION_NAME(<argument>,<argument>...)OVER(<Partition-Clause><Order-by-Clause><Windowing Clause>)例:sum(sal) over (partition by deptno order by ename) new_aliassum就是函数名(sal)是分析函数的参数,每个函数有0~3个参数,参数可以是表达式,例如:sum(sal+comm) over 是一个关键字,用于标识分析函数,否则查询分析器不能区别sum()聚集函数和sum()分析函数partition by deptno 是可选的分区子句,如果不存在任何分区子句,则全部的结果集可看作一个单一的大区order by ename 是可选的order by 子句,有些函数需要它,有些则不需要.依靠已排序数据的那些函数,如:用于访问结果集中前一行和后一行的LAG和LEAD,必须使用,其它函数,如AVG,则不需要.在使用了任何排序的开窗函数时,该子句是强制性的,它指定了在计算分析函数时一组内的数据是如何排序的.1)FUNCTION子句ORACLE提供了26个分析函数,按功能分5类分析函数分类等级(ranking)函数:用于寻找前N种查询开窗(windowing)函数:用于计算不同的累计,如SUM,COUNT,AVG,MIN,MAX等,作用于数据的一个窗口上例:sum(t.sal) over (order by t.deptno,t.ename) running_total,sum(t.sal) over (partition by t.deptno order by t.ename) department_total制表(reporting)函数:与开窗函数同名,作用于一个分区或一组上的所有列例:sum(t.sal) over () running_total2,sum(t.sal) over (partition by t.deptno) department_total2制表函数与开窗函数的关键不同之处在于OVER语句上缺少一个ORDER BY子句!LAG,LEAD函数:这类函数允许在结果集中向前或向后检索值,为了避免数据的自连接,它们是非常有用的.VAR_POP,VAR_SAMP,STDEV_POPE及线性的衰减函数:计算任何未排序分区的统计值2)PARTITION子句按照表达式分区(就是分组),如果省略了分区子句,则全部的结果集被看作是一个单一的组3)ORDER BY子句分析函数中ORDER BY的存在将添加一个默认的开窗子句,这意味着计算中所使用的行的集合是当前分区中当前行和前面所有行,没有ORDER BY时,默认的窗口是全部的分区在Order by 子句后可以添加nulls last,如:order by comm desc nulls last 表示排序时忽略comm列为空的行.4)WINDOWING子句用于定义分析函数将在其上操作的行的集合Windowing子句给出了一个定义变化或固定的数据窗口的方法,分析函数将对这些数据进行操作默认的窗口是一个固定的窗口,仅仅在一组的第一行开始,一直继续到当前行,要使用窗口,必须使用ORDER BY子句根据2个标准可以建立窗口:数据值的范围(RANGES)或与当前行的行偏移量.5)Rang窗口Range 5 preceding:将产生一个滑动窗口,他在组中拥有当前行以前5行的集合ANGE窗口仅对NUMBERS和DATES起作用,因为不可能从VARCHAR2中增加或减去N个单元另外的限制是ORDER BY中只能有一列,因而范围实际上是一维的,不能在N维空间中例:avg(t.sal) over(order by t.hiredate asc range 100 preceding) 统计前100天平均工资6)Row窗口利用ROW分区,就没有RANGE分区那样的限制了,数据可以是任何类型,且ORDER BY 可以包括很多列7)Specifying窗口UNBOUNDED PRECEDING:这个窗口从当前分区的每一行开始,并结束于正在处理的当前行CURRENT ROW:该窗口从当前行开始(并结束)Numeric Expression PRECEDING:对该窗口从当前行之前的数字表达式(Numeric Expression)的行开始,对RANGE来说,从行序值小于数字表达式的当前行的值开始. Numeric Expression FOLLOWING:该窗口在当前行Numeric Expression行之后的行终止(或开始),且从行序值大于当前行Numeric Expression行的范围开始(或终止)range between 100 preceding and 100 following:当前行100前, 当前行100后注意:分析函数允许你对一个数据集进排序和筛选,这是SQL从来不能实现的.除了最后的Order by子句之外,分析函数是在查询中执行的最后的操作集,这样的话,就不能直接在谓词中使用分析函数,即不能在上面使用where或having子句!!!下面我们通过一个实际的例子:按区域查找上一年度订单总额占区域订单总额20%以上的客户,来看看分析函数的应用。
oracle的开窗函数
oracle的开窗函数开窗函数指的是OVER(),和分析函数配合使⽤。
语法:OVER(PARTITION BY分组字段ORDER BY排序字段 ROWS BETWEEN排序字段范围值1 AND排序字段范围值2)语法说明:开窗函数为分析函数带有的,包含三个分析⼦句:1. 分组(PARTITION BY)。
2. 排序(ORDER BY)。
3. 窗⼝(ROWS)-- 指定范围。
ROWS 有多个范围值:1. UNBOUNDED PRECEDING ⽆限/不限定先前⾏。
2. N PRECEDING N个先前⾏(N为1则是1个先前⾏,2则是2个先前⾏,以此类推)。
3. UNBOUNDED FOLLOWING ⽆限/不限定的跟随⾏。
4. N FOLLOWING N个跟随⾏(N为1则是1个跟随⾏,2则是2个跟随⾏,以此类推)。
5. CURRENT ROW 当前⾏。
⽰例1:SELECTCCTI.CTR_TYPE_ID,CCTI.ORDER_NUM,,WMSYS.WM_CONCAT() OVER(PARTITION BY CCTI.CTR_TYPE_ID) CTR_TYPE_ITEM_STRFROM T_CTRG_CTR_TYPE_ITEM CCTI;结果1:分析1:区别于GROUP BY⼦句的只返回分组⾏的结果,开窗函数每⼀⾏都会返回⼀个结果。
⽰例1的写法相当于指定了ROWS范围从不限定先前⾏到不限定跟随⾏(默认):SELECTCCTI.CTR_TYPE_ID,CCTI.ORDER_NUM,,WMSYS.WM_CONCAT() OVER(PARTITION BY CCTI.CTR_TYPE_ID ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) CTR_TYPE_ITEM_STRFROM T_CTRG_CTR_TYPE_ITEM CCTI;⽰例2:SELECTCCTI.CTR_TYPE_ID,CCTI.ORDER_NUM,,WMSYS.WM_CONCAT() OVER(PARTITION BY CCTI.CTR_TYPE_ID ORDER BY CCTI.ORDER_NUM) CTR_TYPE_ITEM_STRFROM T_CTRG_CTR_TYPE_ITEM CCTI;结果2:分析2:加上了ORDER BY 之后,返回结果变成了逐级递增的效果。
开窗函数用法
开窗函数OVER(PARTITION BY)函数介绍开窗函数Oracle从8.1.6开始提供分析函数,分析函数用于计算基于组的某种聚合值,它和聚合函数的不同之处是:对于每个组返回多行,而聚合函数对于每个组只返回一行。
开窗函数指定了分析函数工作的数据窗口大小,这个数据窗口大小可能会随着行的变化而变化,举例如下:1:over后的写法:over(order by salary)按照salary排序进行累计,order by是个默认的开窗函数over(partition by deptno)按照部门分区over(partition by deptno order by salary)2:开窗的窗口范围:over(order by salary range between 5 preceding and 5 following):窗口范围为当前行数据幅度减5加5后的范围内的。
举例:--sum(s)over(order by s range between 2 preceding and 2 following) 表示加2或2的范围内的求和select name,class,s, sum(s)over(order by s range between 2 preceding and 2 following) mm from t2adf 3 45 45 --45加2减2即43到47,但是s在这个范围内只有45asdf 3 55 55cfe 2 74 743dd 3 78 158 --78在76到80范围内有78,80,求和得158fda 1 80 158gds 2 92 92ffd 1 95 190dss 1 95 190ddd 3 99 198gf 3 99 198over(order by salaryrows between 5 preceding and 5 following):窗口范围为当前行前后各移动5行。
数据库-ORACLE开发专题
ORACLE开发专题Oracle开发专题之:分析函数(OVER) (1)Oracle开发专题之:分析函数2(Rank, Dense_rank, row_number) (6)Oracle开发专题之:分析函数3(Top/Bottom N、First/Last、NTile) .. 10 Oracle开发专题之:窗口函数 (15)Oracle开发专题之:报表函数 (20)Oracle开发专题之:分析函数总结 (22)Oracle开发专题之:26个分析函数 (25)PLSQL开发笔记和小结 (29)分析函数简述 (61)说明: 1)Oracle开发专题99%收集自: /pengpenglin/(偶补充了一点点1%);2) PLSQL开发笔记和小结收集自/cheneyfree/3)分析函数简述收集自/7607759/昆明小虫/ 收集,并补充了一点点1%Oracle开发专题之:分析函数(OVER)目录:===============================================1.Oracle分析函数简介2. Oracle分析函数简单实例3.分析函数OVER解析一、Oracle分析函数简介:在日常的生产环境中,我们接触得比较多的是OLTP系统(即Online Transaction Process),这些系统的特点是具备实时要求,或者至少说对响应的时间多长有一定的要求;其次这些系统的业务逻辑一般比较复杂,可能需要经过多次的运算。
比如我们经常接触到的电子商城。
在这些系统之外,还有一种称之为OLAP的系统(即Online Aanalyse Process),这些系统一般用于系统决策使用。
通常和数据仓库、数据分析、数据挖掘等概念联系在一起。
这些系统的特点是数据量大,对实时响应的要求不高或者根本不关注这方面的要求,以查询、统计操作为主。
我们来看看下面的几个典型例子:①查找上一年度各个销售区域排名前10的员工②按区域查找上一年度订单总额占区域订单总额20%以上的客户③查找上一年度销售最差的部门所在的区域④查找上一年度销售最好和最差的产品我们看看上面的几个例子就可以感觉到这几个查询和我们日常遇到的查询有些不同,具体有:①需要对同样的数据进行不同级别的聚合操作②需要在表内将多条数据和同一条数据进行多次的比较③需要在排序完的结果集上进行额外的过滤操作分析函数语法:FUNCTION_NAME(<argument>,<argument>...)OVER(<Partition-Clause><Order-by-Clause><Windowing Clause>)例:sum(sal) over (partition by deptno order by ename) new_aliassum就是函数名(sal)是分析函数的参数,每个函数有0~3个参数,参数可以是表达式,例如:sum(sal+comm)over 是一个关键字,用于标识分析函数,否则查询分析器不能区别sum()聚集函数和sum()分析函数partition by deptno 是可选的分区子句,如果不存在任何分区子句,则全部的结果集可看作一个单一的大区order by ename 是可选的order by 子句,有些函数需要它,有些则不需要.依靠已排序数据的那些函数,如:用于访问结果集中前一行和后一行的LAG和LEAD,必须使用,其它函数,如AVG,则不需要.在使用了任何排序的开窗函数时,该子句是强制性的,它指定了在计算分析函数时一组内的数据是如何排序的.1)FUNCTION子句ORACLE提供了26个分析函数,按功能分5类分析函数分类等级(ranking)函数:用于寻找前N种查询开窗(windowing)函数:用于计算不同的累计,如SUM,COUNT,AVG,MIN,MAX等,作用于数据的一个窗口上例:sum(t.sal) over (order by t.deptno,t.ename) running_total,sum(t.sal) over (partition by t.deptno order by t.ename) department_total制表(reporting)函数:与开窗函数同名,作用于一个分区或一组上的所有列例:sum(t.sal) over () running_total2,sum(t.sal) over (partition by t.deptno ) department_total2制表函数与开窗函数的关键不同之处在于OVER语句上缺少一个ORDER BY子句!LAG,LEAD函数:这类函数允许在结果集中向前或向后检索值,为了避免数据的自连接,它们是非常用用的.VAR_POP,VAR_SAMP,STDEV_POPE及线性的衰减函数:计算任何未排序分区的统计值2)PARTITION子句按照表达式分区(就是分组),如果省略了分区子句,则全部的结果集被看作是一个单一的组3)ORDER BY子句分析函数中ORDER BY的存在将添加一个默认的开窗子句,这意味着计算中所使用的行的集合是当前分区中当前行和前面所有行,没有ORDER BY时,默认的窗口是全部的分区在Order by 子句后可以添加nulls last,如:order by comm desc nulls last 表示排序时忽略comm列为空的行.4)WINDOWING子句用于定义分析函数将在其上操作的行的集合Windowing子句给出了一个定义变化或固定的数据窗口的方法,分析函数将对这些数据进行操作默认的窗口是一个固定的窗口,仅仅在一组的第一行开始,一直继续到当前行,要使用窗口,必须使用ORDER BY子句根据2个标准可以建立窗口:数据值的范围(RANGES)或与当前行的行偏移量.5)Rang窗口Range 5 preceding:将产生一个滑动窗口,他在组中拥有当前行以前5行的集合ANGE窗口仅对NUMBERS和DATES起作用,因为不可能从VARCHAR2中增加或减去N个单元另外的限制是ORDER BY中只能有一列,因而范围实际上是一维的,不能在N维空间中例:avg(t.sal) over(order by t.hiredate asc range 100 preceding) 统计前100天平均工资6)Row窗口利用ROW分区,就没有RANGE分区那样的限制了,数据可以是任何类型,且ORDER BY 可以包括很多列7)Specifying窗口UNBOUNDED PRECEDING:这个窗口从当前分区的每一行开始,并结束于正在处理的当前行CURRENT ROW:该窗口从当前行开始(并结束)Numeric Expression PRECEDING:对该窗口从当前行之前的数字表达式(Numeric Expression)的行开始,对RANGE来说,从从行序值小于数字表达式的当前行的值开始.Numeric Expression FOLLOWING:该窗口在当前行Numeric Expression行之后的行终止(或开始),且从行序值大于当前行Numeric Expression行的范围开始(或终止)range between 100 preceding and 100 following:当前行100前,当前后100后注意:分析函数允许你对一个数据集进排序和筛选,这是SQL从来不能实现的.除了最后的Order by子句之外,分析函数是在查询中执行的最后的操作集,这样的话,就不能直接在谓词中使用分析函数,即不能在上面使用where或having子句!!!二、Oracle分析函数简单实例:下面我们通过一个实际的例子:按区域查找上一年度订单总额占区域订单总额20%以上的客户,来看看分析函数的应用。
oracle常用的分析函数
oracle常⽤的分析函数常⽤的分析函数如下所列:row_number() over(partition by ... order by ...)rank() over(partition by ... order by ...)dense_rank() over(partition by ... order by ...)count() over(partition by ... order by ...)max() over(partition by ... order by ...)min() over(partition by ... order by ...)sum() over(partition by ... order by ...)avg() over(partition by ... order by ...)first_value() over(partition by ... order by ...)last_value() over(partition by ... order by ...)lag() over(partition by ... order by ...)lead() over(partition by ... order by ...)⼀、Oracle分析函数简介:在⽇常的⽣产环境中,我们接触得⽐较多的是OLTP系统(即Online Transaction Process),这些系统的特点是具备实时要求,或者⾄少说对响应的时间多长有⼀定的要求;其次这些系统的业务逻辑⼀般⽐较复杂,可能需要经过多次的运算。
⽐如我们经常接触到的电⼦商城。
在这些系统之外,还有⼀种称之为OLAP的系统(即Online Aanalyse Process),这些系统⼀般⽤于系统决策使⽤。
通常和数据仓库、数据分析、数据挖掘等概念联系在⼀起。
这些系统的特点是数据量⼤,对实时响应的要求不⾼或者根本不关注这⽅⾯的要求,以查询、统计操作为主。
Oracle之分析函数
Oracle之分析函数⼀、分析函数 1、分析函数 分析函数是Oracle专门⽤于解决复杂报表统计需求的功能强⼤的函数,它可以在数据中进⾏分组然后计算基于组的某种统计值,并且每⼀组的每⼀⾏都可以返回⼀个统计值。
2、分析函数和聚合函数的区别 普通的聚合函数⽤group by分组,每个分组返回⼀个统计值,⽽分析函数采⽤partition by分组,并且每组每⾏都可以返回⼀个统计值。
3、分析函数的形式 分析函数带有⼀个开窗函数over(),包含分析⼦句。
分析⼦句⼜由下⾯三部分组成: partition by :分组⼦句,表⽰分析函数的计算范围,不同的组互不相⼲; ORDER BY:排序⼦句,表⽰分组后,组内的排序⽅式; ROWS/RANGE:窗⼝⼦句,是在分组(PARTITION BY)后,组内的⼦分组(也称窗⼝),此时分析函数的计算范围窗⼝,⽽不是PARTITON。
窗⼝有两种,ROWS和RANGE; 使⽤形式如下:OVER(PARTITION BY xxx PORDER BY yyy ROWS BETWEEN rowStart AND rowEnd) 注:窗⼝⼦句在这⾥我只说rows⽅式的窗⼝,range⽅式和滑动窗⼝也不提。
⼆、OVER() 函数 1、sql 查询语句的 order by 和 OVER() 函数中的 ORDER BY 的执⾏顺序 分析函数是在整个sql查询结束后(sql语句中的order by的执⾏⽐较特殊)再进⾏的操作, 也就是说sql语句中的order by也会影响分析函数的执⾏结果: [1] 两者⼀致:如果sql语句中的order by满⾜分析函数分析时要求的排序,那么sql语句中的排序将先执⾏,分析函数在分析时就不必再排序; [2] 两者不⼀致:如果sql语句中的order by不满⾜分析函数分析时要求的排序,那么sql语句中的排序将最后在分析函数分析结束后执⾏排序。
2、分析函数中的分组/排序/窗⼝分析函数包含三个分析⼦句:分组(partition by),排序(order by),窗⼝(rows/range)窗⼝就是分析函数分析时要处理的数据范围,就拿sum来说,它是sum窗⼝中的记录⽽不是整个分组中的记录,因此我们在想得到某个栏位的累计值时,我们需要把窗⼝指定到该分组中的第⼀⾏数据到当前⾏, 如果你指定该窗⼝从该分组中的第⼀⾏到最后⼀⾏,那么该组中的每⼀个sum值都会⼀样,即整个组的总和。
Oracle开发之分析函数简介Over用法
Oracle开发之分析函数简介Over⽤法⼀、Oracle分析函数简介:在⽇常的⽣产环境中,我们接触得⽐较多的是OLTP系统(即Online Transaction Process),这些系统的特点是具备实时要求,或者⾄少说对响应的时间多长有⼀定的要求;其次这些系统的业务逻辑⼀般⽐较复杂,可能需要经过多次的运算。
⽐如我们经常接触到的电⼦商城。
在这些系统之外,还有⼀种称之为OLAP的系统(即Online Aanalyse Process),这些系统⼀般⽤于系统决策使⽤。
通常和数据仓库、数据分析、数据挖掘等概念联系在⼀起。
这些系统的特点是数据量⼤,对实时响应的要求不⾼或者根本不关注这⽅⾯的要求,以查询、统计操作为主。
我们来看看下⾯的⼏个典型例⼦:①查找上⼀年度各个销售区域排名前10的员⼯②按区域查找上⼀年度订单总额占区域订单总额20%以上的客户③查找上⼀年度销售最差的部门所在的区域④查找上⼀年度销售最好和最差的产品我们看看上⾯的⼏个例⼦就可以感觉到这⼏个查询和我们⽇常遇到的查询有些不同,具体有:①需要对同样的数据进⾏不同级别的聚合操作②需要在表内将多条数据和同⼀条数据进⾏多次的⽐较③需要在排序完的结果集上进⾏额外的过滤操作⼆、Oracle分析函数简单实例:下⾯我们通过⼀个实际的例⼦:按区域查找上⼀年度订单总额占区域订单总额20%以上的客户,来看看分析函数的应⽤。
【1】测试环境:复制代码代码如下:SQL> desc orders_tmp;Name Null? Type----------------------- -------- ----------------CUST_NBR NOT NULL NUMBER(5)REGION_ID NOT NULL NUMBER(5)SALESPERSON_ID NOT NULL NUMBER(5)YEAR NOT NULL NUMBER(4)MONTH NOT NULL NUMBER(2)TOT_ORDERS NOT NULL NUMBER(7)TOT_SALES NOT NULL NUMBER(11,2)【2】测试数据:复制代码代码如下:SQL> select * from orders_tmp;CUST_NBR REGION_ID SALESPERSON_ID YEAR MONTH TOT_ORDERS TOT_SALES---------- ---------- -------------- ---------- ---------- ---------- ----------11 7 11 2001 7 2 122044 5 4 2001 10 2 378027 6 7 2001 2 3 375010 6 8 2001 1 2 2169110 6 7 2001 2 3 4262415 7 12 2000 5 6 2412 7 9 2000 6 2 506581 52 20003 2 444941 5 1 2000 92 748642 5 4 20003 2 350602 5 4 2000 4 4 64542 5 1 2000 10 4 355804 5 4 2000 12 2 3919013 rows selected.【3】测试语句:复制代码代码如下:SQL> select o.cust_nbr customer,o.region_id region,sum(o.tot_sales) cust_sales,sum(sum(o.tot_sales)) over(partition by o.region_id) region_sales from orders_tmp owhere o.year = 2001group by o.region_id, o.cust_nbr;CUSTOMER REGION CUST_SALES REGION_SALES---------- ---------- ---------- ------------4 5 37802 378027 6 3750 6806510 6 64315 6806511 7 12204 12204三、分析函数OVER解析:请注意上⾯的绿⾊⾼亮部分,group by的意图很明显:将数据按区域ID,客户进⾏分组,那么Over这⼀部分有什么⽤呢?假如我们只需要统计每个区域每个客户的订单总额,那么我们只需要group by o.region_id,o.cust_nbr就够了。
开窗函数介绍
7934 1300 7782 10 8750
7782 2450 7839 10 8750
7839 5000 10 7450
7369 800 7902 20 6775
7566 2975 7839 20 6775
SQL> select empno,sal,mgr,deptno,
sum(sal) over (partition by deptno order by sal
rows BETWEEN 1 PRECEDING AND 2 FOLLOWING) dd
from emp;
返回结果
EMPNO SAL MGR DEPTNO DD
132 2100 121 50 2100
128 2200 120 50 6500
136 2200 122 50 6500
127 2400 120 50 11300
135 2400 122 50 11300
119 2500 114 30 26300
140 2500 123 50 26300
144 2500 124 50 26300
116 2900 114 30 7900
119 2500 114 30 10800
118 2600 114 30 13900
117 2800 114 30 24900
注意 DEPARTMENT_ID为20、30的DD值和2中的区别
4、over(order by salary range between 50 preceding and 150 following)
上下边界没有限制:OVER (PARTITION BY DEPARTMENT_ID ORDER BY SALARY RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
Oracle开窗函数over()(转)
Oracle开窗函数over()(转)copy⽂链接:/yjjm1990/article/details/7524167#,/database/201402/281473.html格式: 可以开窗的函数(..) over(..) over中防⽌分组的条件和分组的排序,不过分组使⽤的不再是GROUP BY⽽是PARTITION BY,表⽰开窗-- 建表CREATE table tb_sc(uName varchar2(10),uCourse varchar2(10),Uscore varchar2(10));-- 插⼊数据INSERT INTO tb_sc VALUES('张三','语⽂','80');INSERT INTO tb_sc VALUES('张三','数学','95');INSERT INTO tb_sc VALUES('李四','语⽂','90');INSERT INTO tb_sc VALUES('李四','数学','70');INSERT INTO tb_sc VALUES('王五','语⽂','90');INSERT INTO tb_sc VALUES('王五','数学','90');-- 查询所有SELECT * FROM tb_sc;-- 查询每名学⽣的平均分(展⽰姓名、平均分)Select uName,AVG(uScore)FROM tb_scGROUP BY uName;-- 查询每名同学的平均分并降序排列(展⽰姓名、平均分)SELECT uName,AVG(uScore)FROM tb_scGROUP BY uNameORDER BY uName DESC;-- 查询平均分数⾼于85分的学⽣(展⽰姓名、平均分)SELECT uName,AVG(uScore)FROM tb_scGROUP BY uNameHAVING AVG(uScore)>85;-- 查询不为张三且平均分⾼于85的学⽣(展⽰姓名、平均分)SELECT uName,AVG(uScore)FROM tb_scGROUP BY uNameHAVING uName != '张三' AND AVG(uScore) >85;-- 查询所有学⽣的信息并将每个学⽣的各科成绩降序SELECT t.*,ROW_NUMBER() OVER(PARTITION BY t.uName ORDER BY core DESC) RMFROM tb_sc t;-- 查询每个学⽣考得最好的科⽬并展⽰该科⽬的成绩SELECT *FROM(SELECT t.*,row_number() OVER(PARTITION BY t.uName ORDER BY core DESC) rmFROM tb_sc t )WHERE rm=1;-- 注:row_number() over(oartition by 分组字段 order by 排序字段)常⽤于查询所有分组并将各个窗体进⾏排序-- 在开窗函数出现之前存在着很多⽤SQL语句很难解决的问题,很多都要通过复杂的相关⼦查询或者存储过程来完成。
Oracle分析函数Over()
Oracle分析函数Over()阅读⽬录⼀、Over()分析函数1、rank()/dense_rank over(partition by ... order by ...)2、min()/max() over(partition by ...)3、lead()/lag() over(partition by ... order by ...) 取前⾯/后⾯第n⾏记录4、FIRST_VALUE/LAST_VALUE() OVER(PARTITION BY ...) 取⾸尾记录5、ROW_NUMBER() OVER(PARTITION BY.. ORDER BY ..) 排序(应⽤:分页)6、sum/avg/count() over(partition by ..)7、 rows/range between … preceding and … following 上下范围内求值rows between … preceding and … following⼆、其他1、NULLS FIRST/LAST 将空值字段记录放到最前或最后显⽰2、NTILE(n)3、keep(dense_rank first/last)回到顶部⼀、Over()分析函数说明:聚合函数(如sum()、max()等)可以计算基于组的某种聚合值,但是聚合函数对于某个组只能返回⼀⾏记录。
若想对于某组返回多⾏记录,则需要使⽤分析函数。
1、rank()/dense_rank over(partition by ... order by ...)说明:over()在什么条件之上; partition by 按哪个字段划分组; order by 按哪个字段排序;注意: (1)使⽤rank()/dense_rank() 时,必须要带order by否则⾮法 (2)rank()/dense_rank()分级的区别: rank(): 跳跃排序,如果有两个第⼀级时,接下来就是第三级。
Oracle数据库分析函数用法
Oracle数据库分析函数⽤法⽬录1、什么是窗⼝函数?2、窗⼝函数——开窗3、⼀些分析函数的使⽤⽅法4、OVER()参数——分组函数5、OVER()参数——排序函数1、什么是窗⼝函数?窗⼝函数也属于分析函数。
Oracle从8.1.6开始提供窗⼝函数,窗⼝函数⽤于计算基于组的某种聚合值,窗⼝函数指定了分析函数⼯作的数据窗⼝⼤⼩,这个数据窗⼝⼤⼩可能会随着⾏的变化⽽变化。
与聚合函数的不同之处是:对于每个组返回多⾏,⽽聚合函数对于每个组只返回⼀⾏基本语法: ‹分析函数› over (partition by ‹⽤于分组的列名› order by ‹⽤于排序的列名›)。
语法中的‹分析函数›主要由序列函数(rank、dense_rank和row_number等组成)与聚合函数(sum、avg、count、max和min等)作为窗⼝函数组成。
从窗⼝函数组成上看,它是group by 和 order by的功能组合,group by分组汇总后改变了表的⾏数,⼀⾏只有⼀个类别,⽽partiition by则不会减少原表中的⾏数。
恰如窗⼝函数的组成,它同时具有分组和排序的功能,且不减少原表的⾏数。
OVER 关键字表⽰把函数当成窗⼝函数⽽不是聚合函数。
SQL 标准允许将所有聚合函数⽤做窗⼝函数,使⽤ OVER 关键字来区分这两种⽤法。
2、窗⼝函数——开窗OVER 关键字后的括号中经常添加选项⽤以改变进⾏聚合运算的窗⼝范围。
如果 OVER 关键字后的括号中的选项为空,则窗⼝函数会对结果集中的所有⾏进⾏聚合运算。
分析函数 over(partition by 列名 order by 列名 rows between 开始位置 and 结束位置)为什么叫开窗呢?因为在over()括号中的,partition() 函数可以将查询到的数据进⾏单独开⼀个窗⼝处理。
譬如,查询每个班级的学⽣的排名情况,查询每个国家的历年⼈⼝等,诸如此类,都是在查询到的每⼀个班级、每⼀个国家中都开⼀个窗⼝,单独去执⾏命令。
oracle的窗口函数
oracle的窗口函数
Oracle的窗口函数是一种强大的查询工具,它使得在查询中应用聚合函数成为可能,而不会导致分组。
通过使用窗口函数,用户可以计算每行的聚合值,而不是整个查询结果集。
窗口函数也可以用来实现排名和窗口化计算。
Oracle支持多种窗口函数,包括SUM、AVG、COUNT、MAX、MIN 等。
这些函数可以在SELECT语句中使用,并配合OVER子句使用。
使用窗口函数的语法是:
<窗口函数> OVER ([PARTITION BY <列1>,<列2>,…] [ORDER BY <列1>,<列2>,…])
其中,PARTITION BY子句定义了窗口函数的分组,而ORDER BY 子句定义了窗口函数计算的顺序。
通过使用窗口函数,用户可以轻松地进行各种聚合计算,从而更好地理解数据。
- 1 -。
OVER(PARTITIONBY)函数介绍
OVER(PARTITIONBY)函数介绍问题场景 最近在项⽬中遇到了对每⼀个类型进⾏求和并且求该类型所占的⽐例,当时考虑求出每种类型的和,并在java中分别对每⼀种类型的和与总和相除求出所占⽐例。
后来,想到这样有点⿇烦,并且项⽬中持久层使⽤的是iBatis框架,所有考虑从SQL⽅⾯进⾏⼊⼿来简化这个问题。
后来SQL的解决⽅法就为:1SELECT T.CHANNEL AS PATTERN,2COUNT(T.TRANSACTIONKEY) AS T_COUNT,3SUM(T.AMT) AS T_AMT,4ROUND(100*SUM(T.AMT) /SUM(SUM(T.AMT)) OVER(PARTITION BY1), 2) AS AMT_PERCENT,5ROUND(100*COUNT(T.TRANSACTIONKEY) /SUM(COUNT(T.TRANSACTIONKEY)) OVER(PARTITION BY1),2) AS COUNT_PERCENT6FROM XX(表名) T7WHERE T.PARTY_ID ='100579050'8GROUP BY T.CHANNEL 看到这⾥⾃⼰很佩服SQL的强⼤,于是刨根问底,深⼊研究了⼀番Oracel的OVER(PARTITION BY)函数。
简介 开窗函数,Oracle从8.1.6开始提供分析函数,分析函数⽤于计算基于组的某种聚合值,它和聚合函数的不同之处是:对于每个组返回多⾏,⽽聚合函数对于每个组只返回⼀⾏。
开窗函数指定了分析函数⼯作的数据窗⼝⼤⼩,这个数据窗⼝⼤⼩可能会随着⾏的变化⽽变化。
下⾯的测试⽤例数据语句如下: 1create table T2_TEMP(2 NAME varchar2(10) primary key,3 CLASS varchar2(10),4 SROCE NUMBER5 )67insert into T2_TEMP (NAME, CLASS, SROCE)8values ('cfe', '2', 74);910insert into T2_TEMP (NAME, CLASS, SROCE)11values ('dss', '1', 95);1213insert into T2_TEMP (NAME, CLASS, SROCE)14values ('ffd', '1', 95);1516insert into T2_TEMP (NAME, CLASS, SROCE)17values ('fda', '1', 80);1819insert into T2_TEMP (NAME, CLASS, SROCE)20values ('gds', '2', 92);2122insert into T2_TEMP (NAME, CLASS, SROCE)23values ('gf', '3', 99);2425insert into T2_TEMP (NAME, CLASS, SROCE)26values ('ddd', '3', 99);2728insert into T2_TEMP (NAME, CLASS, SROCE)29values ('adf', '3', 45);3031insert into T2_TEMP (NAME, CLASS, SROCE)32values ('asdf', '3', 55);3334insert into T2_TEMP (NAME, CLASS, SROCE)35values ('3dd', '3', 78);View Code 1、over函数的写法: over(partition by class order by sroce)按照sroce排序进⾏累计,order by是个默认的开窗函数,按照class分区。
窗口函数详解
窗⼝函数详解over() 是⼀个常⽤的函数,不管在oralce 还是⼤数据hive-sql 都⽀持。
最近在看SQL的时候,才发现,⾃⼰以前的理解与over()实际使⽤有⼀定的偏差。
使⽤over(order by xxx)按照xxx排序进⾏累计,order by是个默认的开窗函数over(partition by xxx)按照xxx分区over(partition by xxx order by xx)按照xxx分区,并以xx排序⼀般⼤家想到的是这⼏种,其实还有⼀种over()下⾯将以sum()与 over()结合,举⼏个例⼦⽅便理解。
⾸先创建⼀张简单的表(CLIENT):情况⼀over(order by xxx)按照ID排序SELECT NAME, SUM("ID") OVER(ORDER BY "ID" ) FROM CLIENT;得到结果:实现逻辑:按照ID升序排序,第N⾏数据为:第N⾏相等排序值唯⼀时,累加第⼀⾏⾄第N-1⾏值,并加上第N⾏的数据作为第N⾏的最终值;第N⾏相等排序值不唯⼀时,累加第⼀⾏⾄第N-1⾏值,并加上第N⾏的数据*n(n为与第N⾏相同值的个数)数据作为第N⾏的最终值;情况⼆over(partition by xxx)按照xxx分区SELECT NAME, SUM("ID") OVER(PARTITION BY NAME ) FROM CLIENT;得到结果:实现逻辑:某个分区的值:按照 NAME 分区,将与NAME相同分区下的值求和;情况三over(partition by xxx order by xx)按照xxx分区,并以xx排序SELECT NAME, SUM("ID") OVER(PARTITION BY NAME ORDER BY "ID" ) FROM CLIENT;得到结果:实现逻辑:如果理解了前两种实现逻辑,那么这种情况其实很容易理解,就是前两种的结合体。
oracle over()用法
oracle over()用法Oracle OVER()用法在Oracle数据库中,OVER()是一种功能强大的窗口函数,用于对查询结果进行分组和排序。
它可以用于计算聚合函数、排序、分析和显示每个分组的结果。
下面是一些常见的OVER()用法示例:1. 分组统计OVER()可以用于对查询结果进行分组统计。
比如,我们可以使用SUM()函数计算每个部门的销售总额,并在每行结果中显示该部门的总销售额。
SELECT department_id, SUM(sales) OVER (PARTITION BY department_id) AS total_salesFROM sales_table;上面的语句中,PARTITION BY子句指定了按照department_id 字段进行分组,SUM()函数计算每个分组的销售总额,并使用OVER()函数在每行结果中显示该总额。
2. 排序OVER()还可以用于对查询结果进行排序。
例如,我们可以使用ROW_NUMBER()函数为查询结果中的每一行添加一个序号,并按照某个字段进行排序。
SELECT product_id, product_name, ROW_NUMBER() OVER (ORDER BY product_id) AS row_numFROM products_table;上述语句中,ORDER BY子句指定了按照product_id字段进行排序,ROW_NUMBER()函数为每一行结果添加一个序号,并使用OVER()函数应用排序。
3. 分析函数OVER()还可以用于执行更复杂的分析操作。
例如,我们可以使用LAG()函数获取上一行的值,并计算相邻两行的差值。
SELECT value,value - LAG(value, 1, 0) OVER (ORDER BY id) AS di ffFROM values_table;上述语句中,LAG()函数获取上一行的值,diff列计算了当前值与上一行值的差值,并使用OVER()函数指定按照id字段进行排序。
Oracle开发之窗口函数
Oracle开发之窗⼝函数⼀、窗⼝函数简介:到⽬前为⽌,我们所学习的分析函数在计算/统计⼀段时间内的数据时特别有⽤,但是假如计算/统计需要随着遍历记录集的每⼀条记录⽽进⾏呢?举些例⼦来说:①列出每⽉的订单总额以及全年的订单总额②列出每⽉的订单总额以及截⾄到当前⽉的订单总额③列出上个⽉、当⽉、下⼀⽉的订单总额以及全年的订单总额④列出每天的营业额及⼀周来的总营业额⑤列出每天的营业额及⼀周来每天的平均营业额仔细回顾⼀下前⾯我们介绍到的分析函数,我们会发现这些需求和前⾯有⼀些不同:前⾯我们介绍的分析函数⽤于计算/统计⼀个明确的阶段/记录集,⽽这⾥有部分需求例如2,需要随着遍历记录集的每⼀条记录的同时进⾏统计。
也即是说:统计不⽌发⽣⼀次,⽽是发⽣多次。
统计不⾄发⽣在记录集形成后,⽽是发⽣在记录集形成的过程中。
这就是我们这次要介绍的窗⼝函数的应⽤了。
它适⽤于以下⼏个场合:①通过指定⼀批记录:例如从当前记录开始直⾄某个部分的最后⼀条记录结束②通过指定⼀个时间间隔:例如在交易⽇之前的前30天③通过指定⼀个范围值:例如所有占到当前交易量总额5%的记录⼆、窗⼝函数⽰例-全统计:下⾯我们以需求:列出每⽉的订单总额以及全年的订单总额为例,来看看窗⼝函数的应⽤。
【1】测试环境:复制代码代码如下:SQL> desc orders;名称是否为空? 类型----------------------- -------- ----------------MONTH NUMBER(2)TOT_SALES NUMBERSQL>【2】测试数据:复制代码代码如下:SQL> select * from orders;MONTH TOT_SALES---------- ----------1 6106972 4286763 6370314 5411465 5929356 5014857 6069148 4605209 39289810 51011711 53288912 492458已选择12⾏。
oracle的分析函数和开窗函数over()
oracle的分析函数和开窗函数over()⼀什么是分析函数1 概念 分析函数是Oracle专门⽤于解决复杂报表统计需求的功能强⼤的函数,它可以在数据中进⾏分组然后计算基于组的某种统计值,并且每⼀组的每⼀⾏都可以返回⼀个统计值。
2 和聚合函数的区别普通的聚合函数⽤group by分组,每个分组返回⼀个统计值,⽽分析函数采⽤partition by分组,并且每组每⾏都可以返回⼀个统计值。
3 开窗函数开窗函数指定了函数所能影响的窗⼝范围,也就是说在这个窗⼝范围中都可以受到函数的影响,有些分析函数就是开窗函数。
4 分析函数语法function_name (<argument>,<argument>...)OVER(<PARTITION-Clause><ORDER-BY-Clause><Windowing-Clause>)语法解释:1. function_name:对窗⼝中的数据进⾏操作,Oracle常⽤的分析函数有(这⾥就列举了⼀些常⽤的,其实有很多)①聚合函数sum:⼀个组中数据累积和min:⼀个组中数据最⼩值max:⼀个组中数据最⼤值avg:⼀个组中数据平均值count:⼀个组中数据累积计数②排名函数 row_number( ):返回⼀个唯⼀的值,当碰到相同数据时,排名按照记录集中记录的顺序依次递增。
rank( ):返回⼀个唯⼀的值,当碰到相同的数据时,此时所有相同数据的排名是⼀样的,同时会在最后⼀条相同记录和下⼀条不同记录的排名之间空出排名。
dense_rank( ):返回⼀个唯⼀的值,当碰到相同数据时,此时所有相同数据的排名都是⼀样的,同时会在最后⼀条相同记录和下⼀条不同记录的排名之间紧邻递增。
2. over:关键字,⽤于标识分析函数3. Partition-Clause:分区⼦句,根据分区表达式的条件逻辑将单个结果集分成N组格式: partition by...... 4. Order-by-Clause:排序⼦句,⽤于对分区中的数据进⾏排序格式:order by......5. Windowing-Clause:窗⼝⼦句,⽤于定义function在其上操作的⾏的集合,即function所影响的范围格式:order by字段名 range|rows between边界规则1 AND边界规则2边界规则的取值如下表所⽰:可取值说明CURRENT ROW当前⾏N PRECEDING前N⾏UNBOUNDED PRECEDING⼀直到第⼀条记录N FOLLOWING后N⾏UNBOUNDED FOLLOWING⼀直到最后⼀条记录 注意:RANGE表⽰按照值的范围进⾏范围的定义,⽽ROWS表⽰按照⾏的范围进⾏范围的定义⼆分析函数和开窗函数实例1 创建表格并插⼊数据--创建表格create table student(name varchar2(20),city varchar2(20),age int,salary int)--插⼊数据INSERT INTO student(name,city,age,salary) VALUES('Kebi','JiangSu',20,3000);INSERT INTO student(name,city,age,salary) VALUES('James','ChengDu',21,4000);INSERT INTO student(name,city,age,salary) VALUES('Denglun','BeiJing',22,3500);INSERT INTO student(name,city,age,salary) VALUES('Yangmi','London',21,2500);INSERT INTO student(name,city,age,salary) VALUES('Nana','NewYork',22,1000);INSERT INTO student(name,city,age,salary) VALUES('Sunli','BeiJing',20,3000);INSERT INTO student(name,city,age,salary) VALUES('Dengchao','London',22,1500);INSERT INTO student(name,city,age,salary) VALUES('Huge','JiangSu',20,2800);INSERT INTO student(name,city,age,salary) VALUES('Pengyuyan','BeiJing',24,4500);INSERT INTO student(name,city,age,salary) VALUES('Baoluo','London',25,8500);INSERT INTO student(name,city,age,salary) VALUES('Huting','ChengDu',25,3000);INSERT INTO student(name,city,age,salary) VALUES('Hurenxiang','JiangSu',23,2500);表格创建完后,查看表格中的内容2 聚合函数和开窗函数①单⼀的聚合函数count 案例:如果要求出student表中⼀共多少⼈select count(name) from student得到的结果 从上表中看出,得到的结果是⼀个值,即为student表中⼀共12个⼈②聚合函数count和开窗函数over( )的联合使⽤ 案例:如果查询每个⼯资⼩于4000元的员⼯信息(姓名,城市以及⼯资),并在每⾏中都显⽰所有⼯资⼩于4000元的员⼯个数 第⼀种实现⽅式:通过⼦查询实现select name,city ,salary,(select count(salary) from student where salary <4000) ⼯资⼩于4000⼈数from studentwhere salary <4000第⼆种实现⽅式:开窗函数over( )实现select name, city, salary,count(*) over()from studentwhere salary <4000解释⼀下:开窗函数count(*)over( )是对查询结果的每⼀⾏都返回所有符合条件⾏的条数;over关键字后的括号中的选项为空,则开窗函数会对结果集中的所有⾏进⾏聚合运算;over关键字后的括号中的选项为不为空,则按照括号中的范围进⾏聚合运算。
Oracle开窗函数
Oracle开窗函数大略总结一下Oracle的分析函数1. lag(字段1,n) over ([partition by 字段2] order by 字段3),向当前行的后n行提取字段1的值2. lead(字段1,n) over ([partition by 字段2] order by 字段3),向当前行的前n行提取字段1的值3. count(*或字段1) over ([partition by 字段2]),计算总共多少行,注意字段1若是为空,则不包括在行数里面.4.sum(字段1) over ([[partition by 字段2] order by 字段3]),计算和,若有order by,则表示按顺序累计当前行的前面所有行和当前行的字段1值的总和. 注意到,sum是计算所有相同的值后再累加,不管over 里面有没窗口语句.当前行若是最后一行,则后n行的和为null.avg(字段1) over ([[partition by 字段2] order by 字段3])用法相似.4.ntile(n) over (order by 字段1),把所有记录按顺序分成n组.5. row_number()/rank()/dense_rank() over ([partition by 字段2]order by 字段1) ,将返回的记录行按顺序编号.row_number()即使是相同的值,序号也不相同,序号是连续的;rank() 相同的值序号相同,序号是断的,而不是连续的;dense_rank() 相同的值序号相同,序号是连续的.6.非窗口函数,突然想起的. 1>group by rollup(字段1,字段2,字段3.....) :小计总和,select grouping(字段1) 返回0,则是按group by 字段1分组得到的值,返回1则是rollup创建的总和.grouping(字段2)返回0表示按group by 字段2分组的值,返回1表示rollup创建的总和,grouping(字段1)grouping(字段2)group(字段3)...都返回1,表示按字段1,字段2,字段3分组的值,都返回0,则表示rollup创建的总和...rollup会按字段1,(字段1,字段2),(字段1,字段2,字段3),()分组总计,即按N+1种方法分组;--若用group by rollup(a,b)则只会按a分组,ab分组,总计,而不会按b分组with tmp_a as(select 30 deptno,'zz' ename,'analyse' job,to_date('20010203','yyyymmdd') hiredate,500 sal from dual union allselect 10 deptno,'ee' ename,'clerk' job,to_date('20051213','yyyymmdd') hiredate,300 sal from dual union allselect 30 deptno,'cc' ename,'manager' job,to_date('20051213','yyyymmdd') hiredate,10000 sal from dual union allselect 20 deptno,'dd' ename,'analyse' job,to_date('20051213','yyyymmdd') hiredate,6000 sal from dual union allselect 30 deptno,'tt' ename,'clerk' job,to_date('20080212','yyyymmdd') hiredate,600 sal from dual union allselect 30 deptno,'gg' ename,'clerk' job,to_date('20080312','yyyymmdd') hiredate,800 sal from dual union allselect 10 deptno,'rr' ename,'analyse' job,to_date('20090212','yyyymmdd') hiredate,100 sal from dual )select deptno,job,sum(sal),'total by dept and job' categoryfrom tmp_agroup by rollup(deptno,job) --这里只按deptno,job分组和deptno分组和不分组,不会按 job 分组deptno,job,sal,category10 analyse 100 total by dept and job 0 030 analyse 500 total by dept and job 0 030 clerk 1400 total by dept and job 0 020 analyse 6000 total by dept and job 0 030 manager 10000 total by dept and job 0 010 clerk 300 total by dept and job 0 030 11900 total by dept 0 120 6000 total by dept 0 110 400 total by dept 0 1manager 10000 total by job 1 0analyse 6600 total by job 1 0clerk 1700 total by job 1 018300 total for table 1 12>group by cube(字段1,字段2,字段3.....) :小计总和,select grouping(字段1) 返回0,则是按group by 字段1分组得到的值,返回1则是cube创建的总和.grouping(字段2)返回0表示按group by 字段2分组的值,返回1表示cube创建的总和,grouping(字段1)grouping(字段2)group(字段3)...都返回1,表示按字段1,字段2,字段3分组的值,都返回0,则表示cube创建的总和...cube会按字段1,(字段1,字段2),(字段1,字段2,字段3),(),字段2,字段3,(字段1,字段3),(字段2,字段3)分组总计,即按2的N次方种方法分组;--grouping 返回1,则表示cube得到的;返回0,则表示按group得到的with tmp_a as(select 30 deptno,'zz' ename,'analyse' job,to_date('20010203','yyyymmdd') hiredate,500 sal from dual union allselect 10 deptno,'ee' ename,'clerk' job,to_date('20051213','yyyymmdd') hiredate,300 sal from dual union allselect 30 deptno,'cc' ename,'manager' job,to_date('20051213','yyyymmdd') hiredate,10000 sal from dual union allselect 20 deptno,'dd' ename,'analyse' job,to_date('20051213','yyyymmdd') hiredate,6000 sal from dual union allselect 30 deptno,'tt' ename,'clerk' job,to_date('20080212','yyyymmdd') hiredate,600 sal from dual union allselect 30 deptno,'gg' ename,'clerk' job,to_date('20080312','yyyymmdd') hiredate,800 sal from dual union allselect 10 deptno,'rr' ename,'analyse' job,to_date('20090212','yyyymmdd') hiredate,100 sal from dual )selectdeptno,job,sum(sal),decode(grouping(deptno)||grouping(job),'0 0','total by dept and job','01','total by dept','10','total by job','11','total for table') category,grouping(deptno) is_group_deptno,grouping(job)is_group_job from tmp_agroup by cube(deptno,job)order by grouping(deptno),grouping(job)deptno,job,sal,category,is_group_deptno,is_group_job10 analyse 100 total by dept and job 0 030 analyse 500 total by dept and job 0 030 clerk 1400 total by dept and job 0 020 analyse 6000 total by dept and job 0 030 manager 10000 total by dept and job 0 010 clerk 300 total by dept and job 0 030 11900 total by dept 0 120 6000 total by dept 0 110 400 total by dept 0 1manager 10000 total by job 1 0analyse 6600 total by job 1 0clerk 1700 total by job 1 018300 total for table 1 13>group by grouping sets((字段1),(字段2),(字段1,字段2,字段3),()),指定按哪几列分组,即允许定义组.这里定义的是按字段1分组,按字段2分组,按字段1,字段2,字段3一起分组,按()分组即总和.同样grouping(字段1)返回0表示按group by 普通分组所得,返回0则是grouping sets 创建的总和.--如 group by grouping sets(a,b,(a,b),())说明结果会按a分组,按b分组,按ab 分组,总计;也可以直接group by grouping set(())--grouping(a)返回0表示按a分组,返回1表示总计,而不是按a分组了with tmp_a as(select 30 deptno,'zz' ename,'analyse' job,to_date('20010203','yyyymmdd') hiredate,500 sal from dual union allselect 10 deptno,'ee' ename,'clerk' job,to_date('20051213','yyyymmdd') hiredate,300 sal from dual union allselect 30 deptno,'cc' ename,'manager' job,to_date('20051213','yyyymmdd') hiredate,10000 sal from dual union allselect 20 deptno,'dd' ename,'analyse' job,to_date('20051213','yyyymmdd') hiredate,6000 sal from dual union allselect 30 deptno,'tt' ename,'clerk' job,to_date('20080212','yyyymmdd') hiredate,600 sal from dual union allselect 30 deptno,'gg' ename,'clerk' job,to_date('20080312','yyyymmdd') hiredate,800 sal from dual union allselect 10 deptno,'rr' ename,'analyse' job,to_date('20090212','yyyymmdd') hiredate,100 sal from dual )selectdeptno,job,sum(sal),decode(grouping(deptno)||grouping(job),'0 0','total by dept and job','01','total by dept','10','total by job','11','total for table') category,grouping(deptno) is_group_deptno,grouping(job) is_group_job from tmp_agroup by grouping sets(deptno,job,(deptno,job),())order by grouping(deptno),grouping(job)deptno,job,sum(sal),category,is_group_deptno,is_group_job30 analyse 500 total by dept and job 0 010 clerk 300 total by dept and job 0 030 manager 10000 total by dept and job 0 010 analyse 100 total by dept and job 0 020 analyse 6000 total by dept and job 0 030 clerk 1400 total by dept and job 0 030 11900 total by dept 0 110 400 total by dept 0 120 6000 total by dept 0 1manager 10000 total by job 1 0analyse 6600 total by job 1 0clerk 1700 total by job 1 018300 total for table 1 17.oracle分析函数的语法:function_name(arg1,arg2,...)over( )说明:1. partition-clause 数据记录集分组2. order-by-clause 数据记录集排序3. windowing clause 功能非常强大、比较复杂,定义分析函数在操作行的集合这是讲讲windowing clause部分a、窗口使用前提:分析函数必须有order-by-clause语句b、默认窗口范围:RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROWc、窗口有三种:range、row、specifyingrange窗口(值范围,此值对order by 后的字段的值来说)只对日期和数字类型数据生效,只能按照一个字段排序,在对应的字段数据范围内进行搜索.说明范围和排序的升降有关a、升序,查找[本行字段数据值-range值,本行数据值]数据集合b、降序, 查找[本行数据值,本行字段数据值+range值,]数据集合例:查询本人工资以及和本人工资差距在100内的员工个数,即和自己工资相等的员工个数(包括自己)with tmp_a as(select 30 deptno,7723 mgr,'zz' ename,'analyse' job,to_date('20010203','yyyymmdd') hiredate,500 sal from dual union allselect 10 deptno,7723 mgr,'ee' ename,'clerk' job,to_date('20051213','yyyymmdd') hiredate,300 sal from dual union allselect 30 deptno,7725 mgr,'cc' ename,'manager' job,to_date('20051213','yyyymmdd') hiredate,10000 sal fromdual union allselect 30 deptno,7725 mgr,'qq' ename,'manager' job,to_date('20051214','yyyymmdd') hiredate,50000 sal from dual union allselect 30 deptno,7725 mgr,'qq2' ename,'manager' job,to_date('20051215','yyyymmdd') hiredate,40000 sal from dual union allselect 30 deptno,7725 mgr,'qq3' ename,'manager' job,to_date('20051217','yyyymmdd') hiredate,30000 sal from dual union allselect 30 deptno,7725 mgr,'qq4' ename,'manager' job,to_date('20051216','yyyymmdd') hiredate,20000 sal from dual union allselect 30 deptno,7725 mgr,'qq5' ename,'manager' job,to_date('20051220','yyyymmdd') hiredate,20000 sal from dual union allselect 20 deptno,7733 mgr,'dd' ename,'analyse' job,to_date('20051213','yyyymmdd') hiredate,6000 sal from dual union allselect 30 deptno,7725 mgr,'tt' ename,'clerk' job,to_date('20080212','yyyymmdd') hiredate,600 sal from dual union allselect 30 deptno,7723 mgr,'gg' ename,'clerk' job,to_date('20080312','yyyymmdd') hiredate,800 sal from dual union allselect 30 deptno,7723 mgr,'gg2' ename,'clerk' job,to_date('20080315','yyyymmdd') hiredate,800 sal from dual union allselect 30 deptno,7723 mgr,'gg2' ename,'clerk' job,to_date('20080313','yyyymmdd') hiredate,800 sal from dualunion allselect 10 deptno,7724 mgr,'rr' ename,'analyse' job,to_date('20090212','yyyymmdd') hiredate,100 sal from dual )select ename,sal,sum(sal) over (order by sal range 200 preceding) 工资相差在200内的工资和,(count(ename) over (order by sal range 200 preceding))-1 工资相差在200内的员工数,(count(ename) over (order by sal range 0 preceding)) 工资相等员工数 from tmp_aename,sal,工资相差在200内的工资和,工资相差在200内的员工数,工资相等员工数rr 100 100 0 1ee 300 400 1 1zz 500 800 1 1tt 600 1100 1 1gg 800 3000 3 3gg2 800 3000 3 3gg2 800 3000 3 3dd 6000 6000 0 1cc 10000 10000 0 1qq5 20000 40000 1 2qq4 20000 40000 1 2qq3 30000 30000 0 1qq2 40000 40000 0 1qq 50000 50000 0 1--与自己入职日期相差在2天内的员工的工资和(包括自己)with tmp_a as(select 30 deptno,7723 mgr,'zz' ename,'analyse' job,to_date('20010203','yyyymmdd') hiredate,500 sal from dual union allselect 10 deptno,7723 mgr,'ee' ename,'clerk' job,to_date('20051213','yyyymmdd') hiredate,300 sal from dual union allselect 30 deptno,7725 mgr,'cc' ename,'manager' job,to_date('20051213','yyyymmdd') hiredate,10000 sal from dual union allselect 30 deptno,7725 mgr,'qq' ename,'manager' job,to_date('20051214','yyyymmdd') hiredate,50000 sal from dual union allselect 30 deptno,7725mgr,'qq2' ename,'manager' job,to_date('20051215','yyyymmdd') hiredate,40000 sal from dual union allselect 30 deptno,7725 mgr,'qq3' ename,'manager' job,to_date('20051217','yyyymmdd') hiredate,30000 sal from dual union allselect 30 deptno,7725 mgr,'qq4' ename,'manager' job,to_date('20051216','yyyymmdd') hiredate,20000 sal from dual union allselect 30 deptno,7725 mgr,'qq5' ename,'manager' job,to_date('20051220','yyyymmdd') hiredate,20000 sal from dual union allselect 20 deptno,7733 mgr,'dd' ename,'analyse' job,to_date('20051213','yyyymmdd') hiredate,6000 sal from dual union allselect 30 deptno,7725 mgr,'tt' ename,'clerk' job,to_date('20080212','yyyymmdd') hiredate,600 sal from dualunion allselect 30 deptno,7723 mgr,'gg' ename,'clerk' job,to_date('20080312','yyyymmdd') hiredate,800 sal from dual union allselect 30 deptno,7723 mgr,'gg2' ename,'clerk' job,to_date('20080315','yyyymmdd') hiredate,800 sal from dual union allselect 30 deptno,7723 mgr,'gg2' ename,'clerk' job,to_date('20080313','yyyymmdd') hiredate,800 sal from dual union allselect 10 deptno,7724 mgr,'rr' ename,'analyse' job,to_date('20090212','yyyymmdd') hiredate,100 sal from dual )select deptno,mgr,ename,job,hiredate,sal,sum(sal) over (order by hiredate range 2 preceding) rn from tmp_arow 窗口(行范围)row 窗口是设定分析函数的数据行数,使用该窗口基本没有限制rows n preceding即为该窗口数据包括本行前的 n 行以及本行共 (n+1) 行数据specifying 窗口实际上统计的函数都是由specifying 窗口设定,range 、row 窗口实际是指定了分析的对象(字段、数据行),而具体的行数由specifying 窗口设定,常用表达式如下:unbounded preceding 从当前分区第一行开始,结束于处理的当前行current row 从当前行开始 ( 并结束 )numberic expression preceding 从当前行的数字表达式之前的行开始numberic expression following 从当前行的数字表达式之后的行结束over (order by 字段) 默认为over (order by 字段range between unbounded preceding and current row)或over (order by 字段 rows between unbounded preceding and current row)。
Oracle语法之OVER(PARTITIONBY)及开窗函数
Oracle语法之OVER(PARTITIONBY)及开窗函数oracle的分析函数over 及开窗函数⼀:分析函数overOracle从8.1.6开始提供分析函数,分析函数⽤于计算基于组的某种聚合值,它和聚合函数的不同之处是对于每个组返回多⾏,⽽聚合函数对于每个组只返回⼀⾏。
下⾯通过⼏个例⼦来说明其应⽤。
1:统计某商店的营业额。
date sale1 202 153 144 185 30规则:按天统计:每天都统计前⾯⼏天的总额得到的结果:DATE SALE SUM----- -------- ------1 20 20 --1天2 15 35 --1天+2天3 14 49 --1天+2天+3天4 18 67 .5 30 97 .2:统计各班成绩第⼀名的同学信息NAME CLASS S----- ----- ----------------------fda 1 80ffd 1 78dss 1 95cfe 2 74gds 2 92gf 3 99ddd 3 99adf 3 45asdf 3 553dd 3 78通过:--select * from(select name,class,s,rank()over(partition by class order by s desc) mm from t2)where mm=1--得到结果:NAME CLASS S MM----- ----- ---------------------- ----------------------dss 1 95 1gds 2 92 1gf 3 99 1ddd 3 99 1注意:1.在求第⼀名成绩的时候,不能⽤row_number(),因为如果同班有两个并列第⼀,row_number()只返回⼀个结果2.rank()和dense_rank()的区别是:--rank()是跳跃排序,有两个第⼆名时接下来就是第四名--dense_rank()l是连续排序,有两个第⼆名时仍然跟着第三名3.分类统计 (并显⽰信息)A B C-- -- ----------------------m a 2n a 3m a 2n b 2n b 1x b 3x b 2x b 4h b 3select a,c,sum(c)over(partition by a) from t2得到结果:A B C SUM(C)OVER(PARTITIONBYA)-- -- ------- ------------------------h b 3 3m a 2 4m a 2 4n a 3 6n b 2 6n b 1 6x b 3 9x b 2 9x b 4 9如果⽤sum,group by 则只能得到A SUM(C)-- ----------------------h 3m 4n 6x 9⽆法得到B列值=====select * from test数据:A B C1 1 11 2 21 3 32 2 53 4 6---将B栏位值相同的对应的C 栏位值加总select a,b,c, SUM(C) OVER (PARTITION BY B) C_Sum from testA B C C_SUM1 1 1 11 2 2 72 2 5 71 3 3 33 4 6 6---如果不需要已某个栏位的值分割,那就要⽤ nulleg: 就是将C的栏位值summary 放在每⾏后⾯select a,b,c, SUM(C) OVER (PARTITION BY null) C_Sum from testA B C C_SUM1 1 1 171 2 2 171 3 3 172 2 5 173 4 6 17求个⼈⼯资占部门⼯资的百分⽐SQL> select * from salary;NAME DEPT SAL---------- ---- -----a 10 2000b 10 3000c 10 5000d 20 4000SQL> select name,dept,sal,sal*100/sum(sal) over(partition by dept) percent from salary;NAME DEPT SAL PERCENT---------- ---- ----- ----------a 10 2000 20b 10 3000 30c 10 5000 50d 20 4000 100⼆:开窗函数开窗函数指定了分析函数⼯作的数据窗⼝⼤⼩,这个数据窗⼝⼤⼩可能会随着⾏的变化⽽变化,举例如下:1:over(order by salary)按照salary排序进⾏累计,order by是个默认的开窗函数over(partition by deptno)按照部门分区2:over(order by salary range between 5 preceding and 5 following)每⾏对应的数据窗⼝是之前⾏幅度值不超过5,之后⾏幅度值不超过5例如:对于以下列aa1222345679sum(aa)over(order by aa range between 2 preceding and 2 following)得出的结果是AA SUM---------------------- -------------------------------------------------------1 102 142 142 143 184 185 226 187 229 9就是说,对于aa=5的⼀⾏,sum为 5-1<=aa<=5+2 的和对于aa=2来说,sum=1+2+2+2+3+4=14 ;⼜如对于aa=9 ,9-1<=aa<=9+2 只有9⼀个数,所以sum=9 ;3:其它:over(order by salary rows between 2 preceding and 4 following)每⾏对应的数据窗⼝是之前2⾏,之后4⾏4:下⾯三条语句等效:over(order by salary rows between unbounded preceding and unbounded following)每⾏对应的数据窗⼝是从第⼀⾏到最后⼀⾏,等效:over(order by salary range between unbounded preceding and unbounded following)等效over(partition by null)。
分析函数和开窗函数
分析函数和开窗函数分析函数 分析函数是Oracle专门⽤于解决复杂报表统计需求的功能强⼤的函数,它可以在数据中进⾏分组然后计算基于组的某种统计值,并且每⼀组的每⼀⾏都可以返回⼀个统计值分析函数和聚合函数的区别 普通的聚合函数⽤group by分组,每个分组返回⼀个统计值 分析函数采⽤partition by分组,并且每组每⾏都可以返回⼀个统计值 显⽽易见的区别是,从返回结果上看: 聚合后的记录数可能会减少,因为它对数据源进⾏了group by操作,所以对结果是有影响的,即返回的结果⾥去掉聚合的列后,跟聚合前的结果不⼀样 ⽽分析后的记录数是不变的,因为它的作⽤仅仅在于分析,所以不会对结果有影响,即返回的结果⾥去掉分析的列后,跟分析前的结果是⼀样的分析函数的形式 分析函数要与开窗函数(over())⼀起使⽤,使⽤形式为:分析函数() over()开窗函数(over()) 开窗函数(over())包含三个分析⼦句: 分组⼦句(partition by) 排序⼦句(order by) 窗⼝⼦句(rows) 开窗函数(over())使⽤形式如下: over(partition by xxx order by yyy rows between zzz) 开窗函数⾥的"窗",即"窗⼝",表⽰分析函数分析时要处理的数据范围 ⽐如分析函数sum(),它所针对的数据范围为窗⼝中的记录,⽽不是整个表的记录 要获取某个范围的sum值,则需在窗⼝指定具体的数据范围 ⽐如指定该窗⼝从该分组中的第⼀⾏到最后⼀⾏,那么该组中的每⼀个sum值都会⼀样,即整个组的总和 窗⼝⼦句除了rows⽅式的窗⼝,还包括range⽅式和滑动窗⼝ 排序⼦句(order by) 排序⼦句的使⽤⽅法跟sql中的order by⼀样,如:order by colA desc, colB asc nulls first, colC nulls last 开窗函数的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) 如果没有窗⼝⼦句(rows),则默认当前组的第⼀⾏到当前⾏ ⽆论是否省略分组⼦句,都有: 窗⼝⼦句(rows)不能单独存在,必须有order by⼦句时才能出现 相反,有order by⼦句,可以没有窗⼝⼦句(rows) 当省略窗⼝⼦句时 如果存在order by,则默认的窗⼝是unbounded preceding and current row,即当前组的第⼀⾏到当前⾏ 如果不存在order by,则默认的窗⼝是unbounded preceding and unbounded following,即整个组 例如:lag(sal) over(order by sal) over(order by salary)表⽰意义如下: 1) 由于省略分组⼦句,所以当前组的范围为整个表的数据⾏ 2) 在当前组(此时为整个表的数据⾏)这个范围⾥执⾏排序,即order by salary 3) 分析函数lag(sal)在当前组(此时为整个表的数据⾏)这个范围⾥的窗⼝范围为当前组的第⼀⾏到当前⾏,即分析函数lag(sal)在这个窗⼝范围执⾏ 窗⼝⼦句(rows)的相关关键字: preceding:表⽰在...之前 1 preceding:表⽰当前记录的前1条记录 2 preceding:表⽰当前记录的前2条记录 n preceding:表⽰当前记录的前n条记录 unbounded preceding:不受控制的,⽆限的, 若⽆分组,则表⽰所有记录的第1条记录 若有分组,则表⽰分组后,组内的第1条记录 following:表⽰在...之后 1 following:表⽰当前记录的后⼀条记录 2 following:表⽰当前记录的后两条记录 n following:表⽰当前记录的后n条记录 unbounded following:不受控制的,⽆限的, 若⽆分组,则表⽰所有记录的最后⼀条记录 若有分组,则表⽰分组后,组内的最后⼀条记录 相关⽤例: rows between unbounded preceding and unbounded following:针对所有记录 rows between unbounded preceding and current row:针对第⼀条记录到当前记录 rows between current row and unbounded following:针对当前记录到最后⼀条记录 rows between 1 preceding and current row:针对当前记录的上⼀⾏记录到当前⾏记录 rows between current row and 3 following:针对当前记录到当前⾏记录的后三条记录 rows between 1 preceding and 2 following:针对当前记录的上⼀条记录 ~~ 当前⾏记录的后两条记录 当开窗函数over()出现分组(partition by)⼦句时 unbounded preceding即表中⼀个分组⾥的第⼀⾏,unbounded following即表中⼀个分组⾥的最后⼀⾏ 当开窗函数over()省略了分组(partition by)⼦句时 unbounded preceding即表中的第⼀⾏, unbounded following即表中的最后⼀⾏ 使⽤⽰例:select t.id,,t.city,t.sales,--按城市分组,且组内销量升序排列,并获取当前记录针对上⼀条记录到下⼀条记录范围内的最⼩销量值min(t.sales) over(partition by t.city order by t.sales rows between1 preceding and1 following) as col1,--按城市分组,且组内销量升序排列,并获取当前记录针对第⼀条记录到当前记录范围内的最⼩销量值min(t.sales) over(partition by t.city order by t.sales rows between unbounded preceding and current row) as col2, --按城市分组,且组内销量升序排列,并获取当前记录针对上三条记录到当前记录范围内的最⼩销量值min(t.sales) over(partition by t.city order by t.sales rows between3 preceding and current row) as col3from dataset t。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
oracle之分析函数over及开窗函数
一:分析函数over
Oracle从8.1.6开始提供分析函数,分析函数用于计算基于组的某种聚合值,它和聚合函数的不同之处是对于每个组返回多行,而聚合函数对于每个组只返回一行。
统计各班成绩第一名的同学信息
NAME CLASS S
----- -----
----------------------
fda 1 80
ffd 1
78
dss 1 95
cfe 2
74
gds 2 92
gf 3
99
ddd 3 99
adf 3
45
asdf 3 55
3dd 3 78
通过:
--
select *
from
(
select name,class,s,rank()over(partition by class order by s desc) mm
from t2
)
where mm=1
----
得到结果:
NAME CLASS
S
MM
----- ----- ---------------------- ----------------------
dss
1 95 1
gds 2
92 1
gf 3
99 1
ddd 3
99 1
注意:
1.在求第一名成绩的时候,不能用row_number(),因为如果同班有两个并列第一,
row_number()只返回一个结果
2.rank()和dense_rank()的区别是:
--rank()是跳跃排序,有两个第二名时接下来就是第四名
--dense_rank()l是连续排序,有两个第二名时仍然跟着第三名
二:开窗函数
开窗函数指定了分析函数工作的数据窗口大小,这个数据窗口大小可能会随着行的变化而变化,举例如下:
1:
over(order by salary)按照salary排序进行累计,order by是个默认的开窗函数over(partition by deptno)按照部门分区
2:
over(order by salary range between 5 preceding and 5 following)
每行对应的数据窗口是之前行幅度值不超过5,之后行幅度值不超过5
例如:对于以下列
aa
1
2
2
2
3
4
5
6
7
9
SQL>select sum(aa)over(order by aa range between 2 preceding and 2 following)from A1;
得出的结果是
AA SUM
---------------------- -------------------------------------------------------
1 10
2 14
2 14
2 14
3 18
4 18
5 22
6 18
7 22
9 9
就是说,对于aa=5的一行,sum为5-1<=aa<=5+2 的和
对于aa=2来说,sum=1+2+2+2+3+4=14 ;
又如对于aa=9 ,9-1<=aa<=9+2 只有9一个数,所以sum=9 ;
3:其它:
over(order by salary rows between 2 preceding and 4 following)
每行对应的数据窗口是之前2行,之后4行
4:下面三条语句等效:
over(order by salary rows between unbounded preceding and unbounded following)每行对应的数据窗口是从第一行到最后一行,等效:
over(order by salary range between unbounded preceding and unbounded following)
等效
over(partition by null)
--
常用的分析函数如下所列:
row_number() over(partition by ... order by ...) rank() over(partition by ... order by ...)
dense_rank() over(partition by ... order by ...) count() over(partition by ... order by ...)
max() over(partition by ... order by ...)
min() over(partition by ... order by ...)
sum() over(partition by ... order by ...)
avg() over(partition by ... order by ...)
first_value() over(partition by ... order by ...)
last_value() over(partition by ... order by ...)
lag() over(partition by ... order by ...)
lead() over(partition by ... order by ...)
--
--
--
常用的分析函数如下所列:
1、row_number() over(partition by ... order by ...)
2、rank() over(partition by ... order by ...)
3、dense_rank() over(partition by ... order by ...)
4、count() over(partition by ... order by ...)
5、max() over(partition by ... order by ...)
6、min() over(partition by ... order by ...)
7、sum() over(partition by ... order by ...)
8、avg() over(partition by ... order by ...)
9、first_value() over(partition by ... order by ...)
10、last_value() over(partition by ... order by ...)
11、lag() over(partition by ... order by ...)
12、lead() over(partition by ... order by ...)
关于partition by
这些都是分析函数,好像是8.0以后才有的row_number()和rownum差不多,功能更强一点(可以在各个分组内从1开时排序)
rank()是跳跃排序,有两个第二名时接下来就是第四名(同样是在各个分组内)
dense_rank()是连续排序,有两个第二名时仍然跟着第三名。
相比之下row_number是没有重复值的lag(arg1,arg2,arg3):
arg1是从其他行返回的表达式arg2是希望检索的当前行分区的偏移量。
是一个正的偏移量,时一个往回检索以前的行的数目。
arg3是在arg2表示的数目超出了分组的范围时返回的值。
1.
select deptno,row_number() over(partition by deptno order by sal) from
emp order by deptno;
2.
select deptno,rank() over (partition by deptno
order by sal) from emp order by deptno;
3.
select deptno,dense_rank()
over(partition by deptno order by sal) from emp order by deptno;
4.
select
deptno,ename,sal,lag(ename,1,null) over(partition by deptno order by ename) from
emp ord er by deptno;
5.
select deptno,ename,sal,lag(ename,2,'example')
over(partition by deptno order by ename) from em p
order by
deptno;
6.
select deptno, sal,sum(sal) over(partition by deptno) from
emp;--每行记录后都有总计值select deptno, sum(sal) from emp group by deptno;
7.
求每个部门的平均工资以及每个人与所在部门的工资差额
select deptno,ename,sal ,
round(avg(sal) over(partition by deptno))
as dept_avg_sal,
round(sal-avg(sal) over(partition by deptno)) as dept_sal_diff
from emp;。