共计 3228 个字符,预计需要花费 9 分钟才能阅读完成。
概述
之前更新了一篇 Oracle 的函数文章 分析函数并没有包括,这里作为单独的开篇来介绍一下 分析函数
Oracle 函数系列:
Oracle 常见函数大全
Oracle- 分析函数之连续求和 sum(…) over(…)
Oracle- 分析函数之排序值 rank()和 dense_rank()
Oracle- 分析函数之排序后顺序号 row_number()
Oracle- 分析函数之取上下行数据 lag()和 lead()
分析函数是 Oracle 专门用于解决复杂报表统计需求的功能强大的函数,它可以在数据中进行分组然后计算基于组的某种统计值,并且每一组的每一行都可以返回一个统计值。
分析函数和聚合函数的区别
普通的聚合函数用 group by 分组,每个分组返回一个统计值,
分析函数采用 partition by 分组,并且每组每行都可以返回一个统计值。
语法
FUNCTION_NAME(<参数>,…) | |
OVER (<PARTITION BY 表达式,…> | |
<ORDER BY 表达式 <ASC DESC> | |
<NULLS FIRST NULLS LAST>> | |
<WINDOWING 子句>) |
PARTITION 子句 ORDER BY 子句 WINDOWING 子句 缺省时相当于 RANGE UNBOUNDED PRECEDING
分析函数带有一个开窗函数 over(),包含三个分析子句:
- 分组(partition by)
- 排序(order by)
- 窗口(rows)
连续求和分析函数 sum(…) over(…)
sum(…) over …
【功能】连续求和分析函数
【参数】具体参示例
【说明】Oracle 分析函数
NC 示例:
select bdcode,sum(1) over(order by bdcode) aa from bd_bdinfo
【示例】
原表信息
SQL> select deptno ,ename ,sal from emp order by deptno; | |
DEPTNO ENAME SAL | |
------ ---------- --------- | |
10 CLARK 2450.00 | |
10 KING 5000.00 | |
10 MILLER 1300.00 | |
20 JONES 2975.00 | |
20 FORD 3000.00 | |
20 ADAMS 1100.00 | |
20 SMITH 800.00 | |
20 SCOTT 3000.00 | |
30 WARD 1250.00 | |
30 TURNER 1500.00 | |
30 ALLEN 1600.00 | |
30 JAMES 950.00 | |
30 BLAKE 2850.00 | |
30 MARTIN 1250.00 | |
14 rows selected |
规则
sum(…) over(),对所有行求和
sum(…) over(order by …),连续求和
sum(…) over(partition by…),同组内所行求和
sum(…) over(partition by… order by …),同第 1 点中的排序求和原理,只是范围限制在组内
使用 sum(sal) over (order by ename)… 查询员工的薪水“连续”求和,
先来一个简单的,注意 over(…)条件的不同,
使用 sum(sal) over (order by ename)… 查询员工的薪水“连续”求和,
注意 over (order by ename)如果没有 order by 子句,求和就不是“连续”的.
放在一起,体会一下不同之处:
SQL> select e.deptno, | |
2 e.ename, | |
3 e.sal, | |
4 sum(sal) over(order by e.ename) 连续求和, | |
5 sum(sal) over() 总和, -- 此处sum(sal) over () 等同于sum(sal) | |
6 100 * round(sal / sum(sal) over(), 4) "份额(%)" | |
7 from emp e; | |
DEPTNO ENAME SAL 连续求和 总和 份额(%) | |
------ ---------- --------- ---------- ---------- ---------- | |
20 ADAMS 1100.00 1100 29025 3.79 | |
30 ALLEN 1600.00 2700 29025 5.51 | |
30 BLAKE 2850.00 5550 29025 9.82 | |
10 CLARK 2450.00 8000 29025 8.44 | |
20 FORD 3000.00 11000 29025 10.34 | |
30 JAMES 950.00 11950 29025 3.27 | |
20 JONES 2975.00 14925 29025 10.25 | |
10 KING 5000.00 19925 29025 17.23 | |
30 MARTIN 1250.00 21175 29025 4.31 | |
10 MILLER 1300.00 22475 29025 4.48 | |
20 SCOTT 3000.00 25475 29025 10.34 | |
20 SMITH 800.00 26275 29025 2.76 | |
30 TURNER 1500.00 27775 29025 5.17 | |
30 WARD 1250.00 29025 29025 4.31 | |
14 rows selected |
使用子分区查出各部门薪水连续的总和。注意按部门分区。注意 over(…)条件的不同
sum(sal) over (partition by deptno order by ename) 按部门“连续”求总和
sum(sal) over (partition by deptno) 按部门求总和
sum(sal) over (order by deptno,ename) 不按部门“连续”求总和
sum(sal) over () 不按部门,求所有员工总和,效果等同于 sum(sal)。
select deptno, | |
ename, | |
sal, | |
sum(sal) over(partition by deptno order by ename) 部门连续求和, -- 各部门的薪水 "连续" 求和 | |
sum(sal) over(partition by deptno) 部门总和, -- 部门统计的总和,同一部门总和不变 | |
100 * round(sal / sum(sal) over(partition by deptno), 4) "部门份额(%)", | |
sum(sal) over(order by deptno, ename) 连续求和, -- 所有部门的薪水 "连续" 求和 | |
sum(sal) over() 总和, -- 此处sum(sal) over () 等同于sum(sal),所有员工的薪水总和 | |
100 * round(sal / sum(sal) over(), 4) "总份额(%)" | |
from emp |
求和规则有按部门分区的,有不分区的例子
select deptno, | |
ename, | |
sal, | |
sum(sal) over(partition by deptno order by sal) dept_sum, | |
sum(sal) over(order by deptno, sal) sum | |
from emp; |
来一个逆序的,即部门从大到小排列,部门里各员工的薪水从高到低排列,累计和的规则不变。
select deptno, | |
ename, | |
sal, | |
sum(sal) over(partition by deptno order by deptno desc, sal desc ) dept_sum, | |
sum(sal) over(order by deptno desc, sal desc) sum | |
from emp; |
由于两个相同的值都是第一,所以累加时是两个第一相加
总结
在”… from emp;”后面不要加 order by 子句,使用的分析函数的 (partition by deptno order by sal)
里已经有排序的语句了,如果再在句尾添加排序子句,一致倒罢了,不一致,结果就令人费劲了
select deptno, | |
ename, | |
sal, | |
sum(sal) over(partition by deptno order by sal) dept_sum, | |
sum(sal) over(order by deptno , sal) sum | |
from emp | |
order by deptno desc; |
更多 Oracle 相关信息见Oracle 专题页面 http://www.linuxidc.com/topicnews.aspx?tid=12
本文永久更新链接地址:http://www.linuxidc.com/Linux/2016-11/136845.htm
