http://space.itpub.net/7478833/viewspace-511891
row_number() over ([partition by col1] order by col2) ) as 别名
表示根据col1分组,在分组内部根据 col2排序
而这个“别名”的值就表示每组内部排序后的顺序编号(组内连续的唯一的),[partition by col1] 可省略。
以Scott/tiger登陆,以emp表为例。
1、select deptno,ename,sal,
sum(sal) over (order by ename) 累计, --按姓名排序,并将薪水逐个累加
sum(sal) over () 总和 , -- 此处sum(sal) over () 等同于sum(sal),求薪水总和
100*round(sal/sum(sal) over (),4) "份额(%)" --求每个人的薪水占总额的比例,小数点后保留2位,括号和百分号为特殊符号,所以需要“”
from emp
结果如下 :
2、select deptno,ename,sal,
sum(sal) over (partition by deptno order by ename) 部门连续求和,--partition by deptno先按部门分组,再按姓名排序,并将薪水逐个累加
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
结果如下:
3、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;
结果如下:
4、部门从大到小排列,部门里各员工的薪水从高到低排列
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;
结果如下:
5、将各部门的员工按薪水排序
select ename,job,deptno,sal,(row_number() over(partition by deptno order by sal desc)) as 排名 --先按部门分组,再在部门中按薪水降序排名
from scott.emp
结果如下:
6、查找各部门中薪水最高的前2位
select ename,job,deptno,sal,排名 from
(select ename,job,deptno,sal,(row_number() over(partition by deptno order by sal desc)) as 排名
from scott.emp --先将各部门的员工按薪水排序,再在结果中取出需要的部分
) where 排名<=2;
结果如下:
7、如果已经在over()中进行过分组,在"... from emp;"后面不要加order by 子句。
================
http://fxz-2008.iteye.com/blog/1007986
Sql代码
超级牛皮的oracle的分析函数over(Partition by...) 及开窗函数
- over(Partition by...) 一个超级牛皮的ORACLE特有函数。
-
- 最近工作中才接触到这个功能强大而灵活的函数。
-
-
- oracle的分析函数over 及开窗函数
- 一:分析函数over
- Oracle从8.1.6开始提供分析函数,分析函数用于计算基于组的某种聚合值,它和聚合函数的不同之处是
- 对于每个组返回多行,而聚合函数对于每个组只返回一行。
- 下面通过几个例子来说明其应用。
- 1:统计某商店的营业额。
- date sale
- 1 20
- 2 15
- 3 14
- 4 18
- 5 30
- 规则:按天统计:每天都统计前面几天的总额
- 得到的结果:
- DATE SALE SUM
-
- 1 20 20
- 2 15 35
- 3 14 49
- 4 18 67 .
- 5 30 97 .
-
- 2:统计各班成绩第一名的同学信息
- 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()的区别是:
-
-
-
-
- 3.分类统计 (并显示信息)
- A B C
-
- m a 2
- n a 3
- m a 2
- n b 2
- n b 1
- x b 3
- x b 2
- x b 4
- h b 3
- select a,c,sum(c)over(partition by a) from t2
- 得到结果:
- A B C SUM(C)OVER(PARTITIONBYA)
-
- h b 3 3
- m a 2 4
- m a 2 4
- n a 3 6
- n b 2 6
- n b 1 6
- x b 3 9
- x b 2 9
- x b 4 9
-
- 如果用sum,group by 则只能得到
- A SUM(C)
-
- h 3
- m 4
- n 6
- x 9
- 无法得到B列值
-
- =====
- select * from test
-
- 数据:
- A B C
- 1 1 1
- 1 2 2
- 1 3 3
- 2 2 5
- 3 4 6
-
-
-
- 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
-
-
-
- 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
-
- 求个人工资占部门工资的百分比
-
- SQL> select * from salary;
-
- NAME DEPT SAL
-
- a 10 2000
- b 10 3000
- c 10 5000
- d 20 4000
-
- SQL> select name,dept,sal,sal*100/sum(sal) over(partition by dept) percent from salary;
-
- NAME DEPT SAL PERCENT
-
- a 10 2000 20
- b 10 3000 30
- c 10 5000 50
- d 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
- 例如:对于以下列
- aa
- 1
- 2
- 2
- 2
- 3
- 4
- 5
- 6
- 7
- 9
-
- sum(aa)over(order by aa range between 2 preceding and 2 following)
- 得出的结果是
- 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 ...)
-
- 示例
- SQL> select type,qty from test;
-
- TYPE QTY
-
- 1 6
- 2 9
-
- SQL> select type,qty,to_char(row_number() over(partition by type order by qty))||'/'||to_char(count(*) over(partition by type)) as cnt2 from test;
-
- TYPE QTY CNT2
-
- 3 1/2
- 1 6 2/2
- 2 5 1/3
- 7 2/3
- 2 9 3/3
-
- SQL> select * from test;
-
- 1 11111
- 2 22222
- 3 33333
- 4 44444
-
- SQL> select t.id,mc,to_char(b.rn)||'/'||t.id)e
- 2 from test t,
- (select rownum rn from (select max(to_number(id)) mid from test) connect by rownum <=mid ))L
- 4 where b.rn<=to_number(t.id)
- order by id
-
- ID MC TO_CHAR(B.RN)||'/'||T.ID
-
- 1 11111 1/1
- 2 22222 1/2
- 2 22222 2/2
- 3 33333 1/3
- 3 33333 2/3
- 3 33333 3/3
- 44444 1/4 44444 2/4
- 4 44444 3/4CNOUG4 44444 4/4
-
- 10 rows selected
-
- *******************************************************************
-
- 关于partition by
-
- 这些都是分析函数,好像是8.0以后才有的 row_number()和rownum差不多,功能更强一点(可以在各个分组内从1开时排序) rank()是跳跃排序,有两个第二名时接下来就是第四名(同样是在各个分组内) dense_rank()l是连续排序,有两个第二名时仍然跟着第三名。相比之下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;
- 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;
-
-
-
- 本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/hoho_lolo/archive/2010/03/16/5386185.aspx