一:分析函數over
Oracle從8.1.6開始提供分析函數,分析函數用於計算基於組的某種聚合值,它和聚合函數的不同之處是對於每個組返回多行,而聚合函數對於每個組只返回一行。
統計各班成績第一名的同學信息
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()的區別是:
--rank()是跳躍排序,有兩個第二名時接下來就是第四名
--dense_rank()l是連續排序,有兩個第二名時仍然跟着第三名
二:開窗函數
開窗函數指定了分析函數工作的數據窗口大小,這個數據窗口大小可能會隨着行的變化而變化,舉例如下:
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
SQL>select sum(aa)over(order by aa range between 2 preceding and 2 following) from A1;
得出的結果是
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 ...)
| -- |
| -- |
| -- |
常用的分析函數如下所列:
1、row_number() over(partition by ... order by ...)
2、rank() over(partition by ... order by ...)
3、dense_rank() over(partition by ... order by ...)
4、count() over(partition by ... order by ...)
5、max() over(partition by ... order by ...)
6、min() over(partition by ... order by ...)
7、sum() over(partition by ... order by ...)
8、avg() over(partition by ... order by ...)
9、first_value() over(partition by ... order by ...)
10、last_value() over(partition by ... order by ...)
11、lag() over(partition by ... order by ...)
12、lead() over(partition by ... order by ...)
關於partition by
這些都是分析函數,好像是8.0以后才有的 row_number()和rownum差不多,功能更強一點(可以在各個分組內從1開時排序)
rank()是跳躍排序,有兩個第二名時接下來就是第四名(同樣是在各個分組內)
dense_rank()是連續排序,有兩個第二名時仍然跟着第三名。
相比之下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;--每行記錄后都有總計值 select deptno, sum(sal) from emp group by deptno;
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;
