数据库

位置:IT落伍者 >> 数据库 >> 浏览文章

oracle的分析函数over(Partition by...)


发布日期:2018年07月09日
 
oracle的分析函数over(Partition by...)

Sql代码

over(Partition by…) 一个超级牛皮的ORACLE特有函数

最近工作中才接触到这个功能强大而灵活的函数

oracle的分析函数over 及开窗函数

分析函数over

Oracle从开始提供分析函数分析函数用于计算基于组的某种聚合值它和聚合函数的不同之处是对于每个组返回多行而聚合函数对于每个组只返回一行

下面通过几个例子来说明其应用

:统计某商店的营业额

date sale

规则按天统计每天都统计前面几天的总额

得到的结果

DATE SALE SUM

天+

天+天+

:统计各班成绩第一名的同学信息

NAME CLASS S

fda

ffd

dss

cfe

gds

gf

ddd

adf

asdf

dd

通过

select * from

select nameclasssrank()over(partition by class order by s desc) mm from t

where mm=

得到结果

NAME CLASS S MM

dss

gds

gf

ddd

注意

在求第一名成绩的时候不能用row_number()因为如果同班有两个并列第一row_number()只返回一个结果

rank()和dense_rank()的区别是

rank()是跳跃排序有两个第二名时接下来就是第四名

dense_rank()l是连续排序有两个第二名时仍然跟着第三名

分类统计 (并显示信息)

A B C

m a

n a

m a

n b

n b

x b

x b

x b

h b

select acsum(c)over(partition by a) from t

得到结果

A B C SUM(C)OVER(PARTITIONBYA)

h b

m a

m a

n a

n b

n b

x b

x b

x b

如果用sumgroup by 则只能得到

A SUM(C)

h

m

n

x

无法得到B列值

=====

select * from test

数据

A B C

将B栏位值相同的对应的C 栏位值加总

select abc SUM(C) OVER (PARTITION BY B) C_Sum

from test

A B C C_SUM

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

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

select abc SUM(C) OVER (PARTITION BY null) C_Sum

from test

A B C C_SUM

求个人工资占部门工资的百分比

SQL> select * from salary;

NAME DEPT SAL

a

b

c

d

SQL> select namedeptsalsal*/sum(sal) over(partition by dept) percent from salary;

NAME DEPT SAL PERCENT

a

b

c

d

开窗函数

开窗函数指定了分析函数工作的数据窗口大小这个数据窗口大小可能会随着行的变化而变化举例如下

:

over(order by salary) 按照salary排序进行累计order by是个默认的开窗函数

over(partition by deptno)按照部门分区

:

over(order by salary range between preceding and following)

每行对应的数据窗口是之前行幅度值不超过之后行幅度值不超过

例如对于以下列

aa

sum(aa)over(order by aa range between preceding and following)

得出的结果是

AA SUM

对于aa=来说 sum=+++++= ;

又如 对于aa= <=aa<=+ 只有一个数所以sum= ;

:其它

over(order by salary rows between preceding and following)

每行对应的数据窗口是之前之后

:下面三条语句等效

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 …)

示例

SQL> select typeqty from test;

TYPE QTY

SQL> select typeqtyto_char(row_number() over(partition by type order by qty))||/||to_char(count(*) over(partition by type)) as cnt from test;

TYPE QTY CNT

/

/

/

/

/

SQL> select * from test;

SQL> select tidmcto_char(brn)||/||tid)e

from test t

(select rownum rn from (select max(to_number(id)) mid from test) connect by rownum <=mid ))L

where brn<=to_number(tid)

order by id

ID MC TO_CHAR(BRN)||/||TID

/

/

/

/

/

/

/ /

/CNOUG /

rows selected

*******************************************************************

关于partition by

这些都是分析函数好像是以后才有的 row_number()和rownum差不多功能更强一点(可以在各个分组内从开时排序) rank()是跳跃排序有两个第二名时接下来就是第四名(同样是在各个分组内) dense_rank()l是连续排序有两个第二名时仍然跟着第三名相比之下row_number是没有重复值的 lag(argargarg arg是从其他行返回的表达式 arg是希望检索的当前行分区的偏移量是一个正的偏移量时一个往回检索以前的行的数目 arg是在arg表示的数目超出了分组的范围时返回的值

select deptnorow_number() over(partition by deptno order by sal) from emp order by deptno;

select deptnorank() over (partition by deptno order by sal) from emp order by deptno;

select deptnodense_rank() over(partition by deptno order by sal) from emp order by deptno;

select deptnoenamesallag(enamenull) over(partition by deptno order by ename) from emp ord er by deptno;

select deptnoenamesallag(enameexample) over(partition by deptno order by ename) from em p

order by deptno;

select deptno salsum(sal) over(partition by deptno) from emp;每行记录后都有总计值 select deptno sum(sal) from emp group by deptno;

求每个部门的平均工资以及每个人与所在部门的工资差额

select deptnoenamesal

round(avg(sal) over(partition by deptno)) as dept_avg_sal

round(salavg(sal) over(partition by deptno)) as dept_sal_diff

from emp;

上一篇:2008年Oracle错误,备份最热门问题

下一篇:使用impdp复制oracle的schema数据迁移