今天在進行生成庫字段初始化的時候遇到這樣一個需求:web
按照在客戶交易信息表中 按照客戶的帳戶類型分組,並按照日期排序,最後按照分組排序後的順序給一個temp6字段進行順序賦值。sql
小弟本來打算使用group by進行先分組,在排序最後查出rownum id 在進行賦值就ok 。但試了不少方法,group by返回的都只有一行。後來找到了一個神器。over()分析函數。oracle
over(partition by xx列)函數 能夠對該列進行分組 並返回多行(有幾行就返回幾行),最後的函數的概括爲:函數
select t.*,row_number() over(partition by t.account_id order by t.create_time) row_number from me_cus_trade_info t ;spa
這樣就實現了 按帳戶id進行分組,按建立時間排序, 返回全部,和row_number(這個是別名)。3d
將查出的row_number的值插入到temp6中 的sql有些繞,,不過也參照大神的寫出來了orm
update me_cus_trade_info ct
set ct.temp6 =
(select mi.row_number
from (select t.id,
t.account_id,
t.temp6,
row_number() over(partition by t.account_id order by t.create_time) row_number
from me_cus_trade_info t) mi
where ct.id = mi.id)排序
上面的語句是針對全表進行的,要當心執行,,若是要個別執行須要加一些條件好比:ci
where exists (select 1 from me_cus_trade_info t where ct.id = t.id)it
固然over()分析函數的用法功能不止這些:
oracle的分析函數over及開窗函數
一:分析函數over
Oracle從8.1.6開始提供分析函數,分析函數用於計算基於組的某種聚合值,它和聚合函數的不一樣之處是
對於每一個組返回多行,而聚合函數對於每一個組只返回一行。
下面經過幾個例子來講明其應用。
1:統計某商店的營業額。
date sale
1 20
2 15
3 14
4 18
5 30
規則:按天統計:天天都統計前面幾天的總額
select t.* ,sum(sale) over(order by date) sum from example t
獲得的結果:
DATE SALE SUM
—– ——– ——
1 20 20 –1天
2 15 35 –1天+2天
3 14 49 –1天+2天+3天
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
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是連續排序,有兩個第二名時仍然跟着第三名
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列值
—將B欄位值相同的對應的C 欄位值加總,數據:
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
—若是不須要以某個欄位的值分割,那就要用null,這樣就會將C的欄位值sum放在每行後面,也能夠直接空着,不須要填寫,如over()
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
求我的工資佔部門工資的百分比
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
二:開窗函數
開窗函數指定了分析函數工做的數據窗口大小,這個數據窗口大小可能會隨着行的變化而變化,舉例以下:
over(order by salary) 按照salary排序進行累計,order by是個默認的開窗函數
over(partition by deptno)按照部門分區
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 ;
over(order by salary rows between 2 preceding and 4 following)
每行對應的數據窗口是以前2行,以後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 COLUMN ORDER BY COLUMN)
簡單的說row_number()從1開始,爲每一條分組記錄返回一個數字,這裏的ROW_NUMBER() OVER (ORDER BY xlh DESC) 是先把xlh列降序,再爲降序之後的沒條xlh記錄返回一個序號。
示例:
xlh row_num
1700 1
1500 2
1085 3
710 4
row_number() OVER (PARTITION BY COL1 ORDER BY COL2) 表示根據COL1分組,在分組內部根據 COL2排序,而此函數計算的值就表示每組內部排序後的順序編號(組內連續的惟一的)
實例:
create table employee (empid int ,deptid int ,salary decimal(10,2))
insert into employee values(1,10,5500.00)
insert into employee values(2,10,4500.00)
insert into employee values(3,20,1900.00)
insert into employee values(4,20,4800.00)
insert into employee values(5,40,6500.00)
insert into employee values(6,40,14500.00)
insert into employee values(7,40,44500.00)
insert into employee values(8,50,6500.00)
insert into employee values(9,50,7500.00)
數據顯示爲
empid deptid salary
———– ———– ——————-
1 10 5500.00
2 10 4500.00
3 20 1900.00
4 20 4800.00
5 40 6500.00
6 40 14500.00
7 40 44500.00
8 50 6500.00
9 50 7500.00
需求:根據部門分組,顯示每一個部門的工資等級
預期結果:
empid deptid salary rank
———– ———– ————— ———-
1 10 5500.00 1
2 10 4500.00 2
4 20 4800.00 1
3 20 1900.00 2
7 40 44500.00 1
6 40 14500.00 2
5 40 6500.00 3
9 50 7500.00 1
8 50 6500.00 2
SQL腳本:SELECT *, Row_Number() OVER (partition by deptid ORDER BY salary desc) rank FROM employee