table:oracle用戶scott下的emp表 ;
一.
Oracle 從8.1.6開始提供分析函數,分析函數用於計算基於組的某種聚合值,它和聚合函數的不同之處是
對於每個組返回多行,而聚合函數對於每個組只返回一行。
exp:
- 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行值。
- 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:
- select t.empno,
- t.deptno,
- t.ename,
- t.sal,
- sum(t.sal) over(order by t.ename) sum
- 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:
- select t.empno,
- t.deptno,
- t.ename,
- t.sal,
- sum(t.sal) over(partition by t.deptno) sum
- 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:
- 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
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.普通的方法:
- 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)))
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()分析函數:
- 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))
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