OVER(PARTITION BY)函数介绍

摘要:
2010年10月26日-将具有相同字段B值的相应字段C值添加到selecta,B,C,SUM(C)OVER(PARTITIONBYB)C_SumfromtestABCC_SUM11111227225713333466--如果不需要拆分某个字段的值,请使用null:也就是说,将C的字段值摘要放在每行之后,以选择a,B、C,SUM(C)VER(PARITIONBYnull)C_S

2010年10月26日
---将B栏位值相同的对应的C 栏位值加总
select a,b,c, SUM(C) OVER (PARTITION BY B) C_Sum
from test

A B C C_SUM
1 1 1 1
1 2 2 7
2 2 5 7
1 3 3 3
3 4 6 6

---如果不需要已某个栏位的值分割,那就要用 null

eg: 就是将C的栏位值summary 放在每行后面

select a,b,c, SUM(C) OVER (PARTITION BY null) C_Sum
from test

A B C C_SUM
1 1 1 17
1 2 2 17
1 3 3 17
2 2 5 17
3 4 6 17


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 t2
adf 3 45 45 --45加2减2即43到47,但是s在这个范围内只有45
asdf 3 55 55
cfe 2 74 74
3dd 3 78 158 --78在76到80范围内有78,80,求和得158
fda 1 80 158
gds 2 92 92
ffd 1 95 190
dss 1 95 190
ddd 3 99 198

gf 3 99 198


over(order by salary rows between 5 preceding and 5 following):窗口范围为当前行前后各移动5行。
举例:


--sum(s)over(order by s rows between 2 preceding and 2 following)表示在上下两行之间的范围内
select name,class,s, sum(s)over(order by s rows between 2 preceding and 2 following) mm from t2
adf 3 45 174 (45+55+74=174)
asdf 3 55 252 (45+55+74+78=252)
cfe 2 74 332 (74+55+45+78+80=332)
3dd 3 78 379 (78+74+55+80+92=379)
fda 1 80 419
gds 2 92 440
ffd 1 95 461
dss 1 95 480
ddd 3 99 388
gf 3 99 293


over(order by salary range between unbounded preceding and unbounded following)或者
over(order by salary rows between unbounded preceding and unbounded following):窗口不做限制

3、与over函数结合的几个函数介绍


row_number()over()、rank()over()和dense_rank()over()函数的使用
下面以班级成绩表t2来说明其应用

t2表信息如下:
cfe 2 74
dss 1 95
ffd 1 95
fda 1 80
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;
得到的结果是:
dss 1 95 1
ffd 1 95 1
gds 2 92 1
gf 3 99 1
ddd 3 99 1

注意:
1.在求第一名成绩的时候,不能用row_number(),因为如果同班有两个并列第一,row_number()只返回一个结果;
select * from
(
select name,class,s,row_number()over(partition by class order by s desc) mm from t2
)
where mm=1;
1 95 1 --95有两名但是只显示一个
2 92 1
3 99 1 --99有两名但也只显示一个

2.rank()和dense_rank()可以将所有的都查找出来:
如上可以看到采用rank可以将并列第一名的都查找出来;
rank()和dense_rank()区别:
--rank()是跳跃排序,有两个第二名时接下来就是第四名;
select name,class,s,rank()over(partition by class order by s desc) mm from t2
dss 1 95 1
ffd 1 95 1
fda 1 80 3 --直接就跳到了第三
gds 2 92 1
cfe 2 74 2
gf 3 99 1
ddd 3 99 1
3dd 3 78 3
asdf 3 55 4
adf 3 45 5
--dense_rank()l是连续排序,有两个第二名时仍然跟着第三名
select name,class,s,dense_rank()over(partition by class order by s desc) mm from t2
dss 1 95 1
ffd 1 95 1
fda 1 80 2 --连续排序(仍为2)
gds 2 92 1
cfe 2 74 2
gf 3 99 1
ddd 3 99 1
3dd 3 78 2
asdf 3 55 3
adf 3 45 4

--sum()over()的使用
select name,class,s, sum(s)over(partition by class order by s desc) mm from t2 --根据班级进行分数求和
dss 1 95 190 --由于两个95都是第一名,所以累加时是两个第一名的相加
ffd 1 95 190
fda 1 80 270 --第一名加上第二名的
gds 2 92 92
cfe 2 74 166
gf 3 99 198
ddd 3 99 198
3dd 3 78 276
asdf 3 55 331
adf 3 45 376


first_value() over()和last_value() over()的使用

举例说明,例子表数据如下表所示:

利用该函数查询以时间为排序,查找出all_conduit_len最小值和最大值:


select district,
oper_date,
all_conduit_len,
first_value(all_conduit_len) over(partition by oper_date order by all_conduit_len) low,
last_value(all_conduit_len) over(partition by oper_date order by all_conduit_len rows between unbounded preceding and unbounded following) high
from n9_rpt_checkdata;

结果如下所示:

再利用该函数,判断如果district为空,根据rownum排序取值填充:


select district,
oper_date,
all_conduit_len,
last_value(district ignore nulls) over(order by rownum)
from n9_rpt_checkdata;
结果如下:


--lag() over()函数用法(取出前n行数据)
lag(expresstion,<offset>,<default>)
with a as
(select 1 id,'a' name from dual
union
select 2 id,'b' name from dual
union
select 3 id,'c' name from dual
union
select 4 id,'d' name from dual
union
select 5 id,'e' name from dual
)
select id,name,lag(id,1,'')over(order by name) from a;

--lead() over()函数用法(取出后N行数据)
lead(expresstion,<offset>,<default>)
with a as
(select 1 id,'a' name from dual
union
select 2 id,'b' name from dual
union
select 3 id,'c' name from dual
union
select 4 id,'d' name from dual
union
select 5 id,'e' name from dual
)
select id,name,lead(id,1,'')over(order by name) from a;

--ratio_to_report(a)函数用法 Ratio_to_report() 括号中就是分子,over() 括号中就是分母
with a as (select 1 a from dual
union all
select 1 a from dual
union all
select 1 a from dual
union all
select 2 a from dual
union all
select 3 a from dual
union all
select 4 a from dual
union all
select 4 a from dual
union all
select 5 a from dual
)
select a, ratio_to_report(a)over(partition by a) b from a
order by a;

with a as (select 1 a from dual
union all
select 1 a from dual
union all
select 1 a from dual
union all
select 2 a from dual
union all
select 3 a from dual
union all
select 4 a from dual
union all
select 4 a from dual
union all
select 5 a from dual
)
select a, ratio_to_report(a)over() b from a --分母缺省就是整个占比
order by a;

with a as (select 1 a from dual
union all
select 1 a from dual
union all
select 1 a from dual
union all
select 2 a from dual
union all
select 3 a from dual
union all
select 4 a from dual
union all
select 4 a from dual
union all
select 5 a from dual
)
select a, ratio_to_report(a)over() b from a
group by a order by a;--分组后的占比

SQL> select n1,v1,nid,sum(nid) over(order by nid) as sum
2 from t1;

N1 V1 NID SUM
---------- ---------- ---------- ----------
1 aa 61 61
2 aa 62 123
3 aa 63 186
4 aa 64 250

取nid列的累积和,即下面以emp表为例的按部门“连续”求总和

==================================================================

按v1分组取nid的和

SQL> select v1,sum(nid) over (partition by v1 order by v1) as sum_nid from t1;

V1 SUM_NID
---------- ----------
aa 187
aa 187
aa 187
bb 83

按v1分组取nid的和,并重复行只显示一行

SQL> select distinct * from (select v1,sum(nid) over (partition by v1) as sum_nid from t1);

V1 SUM_NID
---------- ----------
aa 187
bb 83

==================================================================

再以emp为例

使用子分区查出各部门薪水连续的总和。注意按部门分区 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)。

sql> break on deptno skip 1 -- 为效果更明显,把不同部门的数据隔段显示。

SQL> select deptno,ename,sal,
2 sum(sal) over (partition by deptno order by ename) 部门连续求和,
3 sum(sal) over (partition by deptno) 部门总和,
4 100*round(sal/sum(sal) over (partition by deptno),4) 部门份额,
5 sum(sal) over () 总和,
6 sum(sal) over (order by deptno,ename) 连续求和,
7 100*round(sal/sum(sal) over (),4) 总份额
8 from emp;

DEPTNO ENAME SAL 部门连续求和 部门总和 部门份额 总和 连续求和 总份额

---------- ---------- ---------- ------------ ---------- ---------- ---------- ---------- ----------

10 CLARK 2450 2450 8750 28 29025 2450 8.44

KING 5000 7450 8750 57.14 29025 7450 17.23

MILLER 1300 8750 8750 14.86 29025 8750 4.48


20 ADAMS 1100 1100 10875 10.11 29025 9850 3.79

FORD 3000 4100 10875 27.59 29025 12850 10.34

JONES 2975 7075 10875 27.36 29025 15825 10.25

SCOTT 3000 10075 10875 27.59 29025 18825 10.34

SMITH 800 10875 10875 7.36 29025 19625 2.76


30 ALLEN 1600 1600 9400 17.02 29025 21225 5.51

BLAKE 2850 4450 9400 30.32 29025 24075 9.82

JAMES 950 5400 9400 10.11 29025 25025 3.27

MARTIN 1250 6650 9400 13.3 29025 26275 4.31

TURNER 1500 8150 9400 15.96 29025 27775 5.17

WARD 1250 9400 9400 13.3 29025 29025 4.31

已选择14行。

综合的例子,求和规则有按部门分区的,有不分区的例子


SQL> select deptno,ename,sum(sal) over(partition by deptno order by sal) as sum_sal,
2 sum(sal) over(order by deptno,sal) as sum_dept_sal
3 from emp;

DEPTNO ENAME SUM_SAL SUM_DEPT_SAL
---------- ---------- ---------- ------------
10 MILLER 1300 1300
CLARK 3750 3750
KING 8750 8750

20 SMITH 800 9550
ADAMS 1900 10650
JONES 4875 13625
SCOTT 10875 19625
FORD 10875 19625

30 JAMES 950 20575
WARD 3450 23075
MARTIN 3450 23075
TURNER 4950 24575
ALLEN 6550 26175
BLAKE 9400 29025


已选择14行。

来一个逆序的,即部门从大到小排列,部门里各员工的薪水从高到低排列,累计和的规则不变。

SQL> select deptno,ename,sal,
2 sum(sal) over (partition by deptno order by deptno desc,sal desc) as sum_sal_order,
3 sum(sal) over (order by deptno desc,sal desc) as sum
4 from emp;

DEPTNO ENAME SAL SUM_SAL_ORDER SUM
---------- ---------- ---------- ------------- ----------
30 BLAKE 2850 2850 2850
ALLEN 1600 4450 4450
TURNER 1500 5950 5950
WARD 1250 8450 8450
MARTIN 1250 8450 8450
JAMES 950 9400 9400

20 SCOTT 3000 6000 15400
FORD 3000 6000 15400
JONES 2975 8975 18375
ADAMS 1100 10075 19475
SMITH 800 10875 20275

10 KING 5000 5000 25275
CLARK 2450 7450 27725
MILLER 1300 8750 29025


已选择14行。



免责声明:文章转载自《OVER(PARTITION BY)函数介绍》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇JAVA继承初始化过程linux --&amp;gt; Linux 的启动流程下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

oracle教程:PLSQL常用方法汇总

oracle教程:PLSQL常用方法汇总 在SQLPLUS下,实现中-英字符集转换alter session set nls_language='AMERICAN';alter session set nls_language='SIMPLIFIED CHINESE';主要知识点:一、有关表的操作1)建表 create table test as sel...

oracle--pl/sql变量定义----

一、变量介绍 在编写pl/sql程序时,可以定义变量和常量;在pl/sql程序中包括有: 1)、标量类型(scalar) 2)、复合类型(composite) --用于操作单条记录 3)、参照类型(reference) --用于操作多条记录 4)、lob(large object) 二、标量(scalar)——常用类型 1)、在编写pl/sql块时,如果...

Burnside引理和Polya定理

一类与对称相关的计数问题 栗子:给一个手镯,上面有 (n) 颗珠子,由线串成环。每种珠子可能有 红、黄、绿、蓝 四种颜色。问本质不同的手镯有多少种。对于两种手镯本质相同,当且仅当一种手镯能通过旋转和翻转变换与另一种手镯重合。 抽象化 对于这类问题,我们规范化定义:设集合 (A) 表示按照顺序编号手镯的每个珠子,(B) 表示四种颜色,(X:A ightarro...

九、oracle 事务

一、什么是事务事务用于保证数据的一致性,它由一组相关的dml语句组成,该组的dml(数据操作语言,增删改,没有查询)语句要么全部成功,要么全部失败。如:网上转账就是典型的要用事务来处理,用于保证数据的一致性。 二、事务和锁当执行事务操作时(dml语句),oracle会在被作用的表上加锁,防止其它用户修改表的结构。这里对我们的用户来讲是非常重要的。 三、提交...

oracle 表空间不足解决办法

Oracle表空间不足,一般有两个原因:   1. 原表空间太小,没有自增长;   2. 表空间已自增长,而且表空间也已足够大 检查原因: 1. 查看表在那个表空间 select tablespace_name,table_name from user_talbes where table_name='test'; 2. 获取用户的默认表空...

20169205实验一 Java开发环境的熟悉(Linux+IDEA)

20169205实验一 Java开发环境的熟悉(Linux+IDEA) 实验内容及步骤 使用JDK编译、运行简单的Java程序 打开windows下的cmd → 输入cd Code命令进入Code目录 → 输入md 20169205建立以自己学号命名的文件夹 → 输入cd 20169205进入文件夹 → 输入md exp1建立“实验一”文件夹 → 输入cd...