oracle 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


返回的結果:

empno ename sum
7369 SMITH 142781.99
7499 ALLEN 142781.99
7521 WARD 142781.99
7566 JONES 142781.99
7654 MARTIN 142781.99
7698 BLAKE 142781.99
7782 CLARK 142781.99
7788 SCOTT 142781.99
7839 KING 142781.99
7844 TURNER 142781.99
7876 ADAMS 142781.99
7900 JAMES 142781.99
7902 FORD 142781.99
7934 MILLER 142781.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


返回的結果:

empno deptno ename     sal       sum
7876 20 ADAMS 4646.11 4646.11
7499 30 ALLEN 8493.66 13139.77
7698 30 BLAKE 15047.69 28187.46
7782 10 CLARK 11823.85 40011.31
7902 20 FORD 14935.97 54947.28
7900 30 JAMES 4935.36 59882.64
7566 20 JONES 15086.30 74968.94
7839 10 KING 23841.13 98810.07
7654 30 MARTIN 6526.80 105336.87
7934 10 MILLER 6167.32 111504.19
7788 20 SCOTT 12710.16 124214.35
7369 20 SMITH 4089.17 128303.52
7844 30 TURNER 7843.77 136147.29
7521 30 WARD 6634.70 142781.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



返回的結果:

empno deptno   ename     sal       sum
7782 10 CLARK 11823.85 41832.3
7839 10 KING 23841.13 41832.3
7934 10 MILLER 6167.32 41832.3
7369 20 SMITH 4089.17 51467.71
7876 20 ADAMS 4646.11 51467.71
7902 20 FORD 14935.97 51467.71
7788 20 SCOTT 12710.16 51467.71
7566 20 JONES 15086.30 51467.71
7499 30 ALLEN 8493.66 49481.98
7698 30 BLAKE 15047.69 49481.98
7654 30 MARTIN 6526.80 49481.98
7900 30 JAMES 4935.36 49481.98
7844 30 TURNER 7843.77 49481.98
7521 30 WARD 6634.70 49481.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



返回的結果:

empno deptno   ename     sal       sum
7782 10 CLARK 11823.85 11823.85
7839 10 KING 23841.13 35664.98
7934 10 MILLER 6167.32 41832.3
7876 20 ADAMS 4646.11 4646.11
7902 20 FORD 14935.97 19582.08
7566 20 JONES 15086.30 34668.38
7788 20 SCOTT 12710.16 47378.54
7369 20 SMITH 4089.17 51467.71
7499 30 ALLEN 8493.66 8493.66
7698 30 BLAKE 15047.69 23541.35
7900 30 JAMES 4935.36 28476.71
7654 30 MARTIN 6526.80 35003.51
7844 30 TURNER 7843.77 42847.28
7521 30 WARD 6634.70 49481.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))


輸出結果是一樣的:

管理員工人數最多的人的名字 他管理的人的名字
BLAKE KING

 

rank()over

分區查最大的一條記錄

select * from  (select t.soft_conf_id,t.pdt_type_id ,rank() over(PARTITION by t.pdt_type_id order by soft_conf_id desc )mm from ta_soft_conf_main t) where mm=1 ;

 

用戶軟件版本前100下載統計SQL

select * from (

select serial_no,auto_type_id,version,sum(dd),row_number()over(order by sum(dd) desc ) orders

from(
    select serial_no,
       auto_type_id,version,1 dd
  from TB_SOFT_DOWNLOAD_DETAIL
 where 1=1
  )
group by serial_no,auto_type_id,version
)
where orders <100

發佈了35 篇原創文章 · 獲贊 0 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章