分析函数OVER

 准备工作:
table:oracle用户scott下的emp表 ;

一.
Oracle 从8.1.6开始提供分析函数,分析函数用于计算基于组的某种聚合值,它和聚合函数的不同之处是

  对于每个组返回多行,而聚合函数对于每个组只返回一行。

exp:
Sql代码   
  1. select t.empno,t.ename,sum(t.sal) from emp t  
select t.empno,t.ename,sum(t.sal) from emp t

这样会报:ORA-00937:非单组分组函数;
结论:聚合函数只能返回1行值。
Sql代码   
  1. select t.empno,t.ename,sum(t.sal)over() sum from emp t  
select t.empno,t.ename,sum(t.sal)over() sum from emp t

返回的结果:
empnoenamesum
7369SMITH142781.99
7499ALLEN142781.99
7521WARD142781.99
7566JONES142781.99
7654MARTIN142781.99
7698BLAKE142781.99
7782CLARK142781.99
7788SCOTT142781.99
7839KING142781.99
7844TURNER142781.99
7876ADAMS142781.99
7900JAMES142781.99
7902FORD142781.99
7934MILLER142781.99

结论:这就是每个组返回多行。

二.
over()、over(order by...)与over(partition by...)之间的区别
1.分析函数over()用在聚合函数(max(),sun()....)后面,可返回多行所有结果的聚合值;
exp:如上;

2.over(order by...)用在聚合函数(max(),sun()....)后面,可返回根据排序结果进行统计到当前行的聚合值(即“连续”统计);
exp:
Sql代码   
  1. select t.empno,   
  2.        t.deptno,   
  3.        t.ename,   
  4.        t.sal,   
  5.        sum(t.sal) over(order by t.ename) sum  
  6.   from emp t  
select t.empno,
       t.deptno,
       t.ename,
       t.sal,
       sum(t.sal) over(order by t.ename) sum
  from emp t

返回的结果:
empnodeptnoename    sal      sum
787620ADAMS4646.114646.11
749930ALLEN8493.6613139.77
769830BLAKE15047.6928187.46
778210CLARK11823.8540011.31
790220FORD14935.9754947.28
790030JAMES4935.3659882.64
756620JONES15086.3074968.94
783910KING23841.1398810.07
765430MARTIN6526.80105336.87
793410MILLER6167.32111504.19
778820SCOTT12710.16124214.35
736920SMITH4089.17128303.52
784430TURNER7843.77136147.29
752130WARD6634.70142781.99

分析:第二行的sum=第一行里的sal+第二行里的sal;
      第二行的sum=第一行里的sal+第二行里的sal+第三行里的sal;
      .....
结论:返回值是根据排序后的结果,当前所在的行进行统计的。

3.over(partition by...)用在聚合函数(max(),sun()....)后面,可根据pratition by里指定的某一列来统计聚合值。
exp:
Sql代码   
  1. select t.empno,   
  2.        t.deptno,   
  3.        t.ename,   
  4.        t.sal,   
  5.        sum(t.sal) over(partition by t.deptno) sum  
  6.   from emp t  
select t.empno,
       t.deptno,
       t.ename,
       t.sal,
       sum(t.sal) over(partition by t.deptno) sum
  from emp t


返回的结果:
empnodeptno  ename    sal      sum
778210CLARK11823.8541832.3
783910KING23841.1341832.3
793410MILLER6167.3241832.3
736920SMITH4089.1751467.71
787620ADAMS4646.1151467.71
790220FORD14935.9751467.71
778820SCOTT12710.1651467.71
756620JONES15086.3051467.71
749930ALLEN8493.6649481.98
769830BLAKE15047.6949481.98
765430MARTIN6526.8049481.98
790030JAMES4935.3649481.98
784430TURNER7843.7749481.98
752130WARD6634.7049481.98

分析:每个sum的值都是把deptno相同的sal值进行求和。
结论:根据pratition by里指定的某一列来统计聚合值。

三.一个综合的例子:
exp:
question:
按部门“连续”求总和;
answer:
Sql代码   
  1. select t.empno,   
  2.        t.deptno,   
  3.        t.ename,   
  4.        t.sal,   
  5.        sum(t.sal) over(partition by t.deptno order by t.ename) sum  
  6.   from emp t  
select t.empno,
       t.deptno,
       t.ename,
       t.sal,
       sum(t.sal) over(partition by t.deptno order by t.ename) sum
  from emp t


返回的结果:
empnodeptno  ename    sal      sum
778210CLARK11823.8511823.85
783910KING23841.1335664.98
793410MILLER6167.3241832.3
787620ADAMS4646.114646.11
790220FORD14935.9719582.08
756620JONES15086.3034668.38
778820SCOTT12710.1647378.54
736920SMITH4089.1751467.71
749930ALLEN8493.668493.66
769830BLAKE15047.6923541.35
790030JAMES4935.3628476.71
765430MARTIN6526.8035003.51
784430TURNER7843.7742847.28
752130WARD6634.7049481.98

分析:先根据partition by 进行分组,然后再根据order by 进行排序“连续”统计。

四.一个实际的例子来说明over()分析函数在代码上能简化和提高效率。
question:
         查询出管理员工人数最多的人的名字和他管理的人的名字
answer:
1.普通的方法:
Sql代码   
  1. select d.ename 管理员工人数最多的人的名字, o.ename 他管理的人的名字   
  2.   from emp d, emp o   
  3.  where o.empno = d.mgr   
  4.    and d.empno in  
  5.        (select p.empno   
  6.           from emp p   
  7.          where p.empno in  
  8.                (select r.mgr   
  9.                   from (select e.mgr, count(e.mgr) c from emp e group by e.mgr) r   
  10.                  where r.c is  
  11.                        (select max(w.z)   
  12.                           from (select count(m.mgr) z from emp m group by m.mgr) w)))  
select d.ename 管理员工人数最多的人的名字, o.ename 他管理的人的名字
  from emp d, emp o
 where o.empno = d.mgr
   and d.empno in
       (select p.empno
          from emp p
         where p.empno in
               (select r.mgr
                  from (select e.mgr, count(e.mgr) c from emp e group by e.mgr) r
                 where r.c is
                       (select max(w.z)
                          from (select count(m.mgr) z from emp m group by m.mgr) w)))

2.使用over()分析函数:
Sql代码   
  1. select e.ename 管理员工人数最多的人的名字, j.ename 他管理的人的名字   
  2.   from emp e, emp j   
  3.  where j.empno = e.mgr   
  4.    and e.empno in (select distinct (r.mgr)   
  5.                      from (select m.mgr,   
  6.                                   count(m.mgr) over(partition by m.mgr order by m.empno) t   
  7.                              from emp m) r   
  8.                     where r.t is (select max(y.h)   
  9.                                from (select count(p.mgr) over(partition by p.mgr order by p.empno) h   
  10.                                             from emp p) y))  
select e.ename 管理员工人数最多的人的名字, j.ename 他管理的人的名字
  from emp e, emp j
 where j.empno = e.mgr
   and e.empno in (select distinct (r.mgr)
                     from (select m.mgr,
                                  count(m.mgr) over(partition by m.mgr order by m.empno) t
                             from emp m) r
                    where r.t is (select max(y.h)
                               from (select count(p.mgr) over(partition by p.mgr order by p.empno) h
                                            from emp p) y))


输出结果是一样的:
管理员工人数最多的人的名字他管理的人的名字
BLAKEKING


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值