一、ROLLUP和CUBE函數,自動彙總數據
select * from test_tbl的數據這樣的
col_a col_b col_c
---- ----- -----
1 b1 12
1 b1 2
1 b2 31
2 b2 7
2 b3 42
2 b3 1
2 b3 3
若是按A、B列進行彙總C列,用通常的方法是這樣:
select col_a,col_b,sum(col_c) from test_tbl group by col_a,col_b 結果以下
col_a col_b sum(col_c)
---- ----- --------
1 b1 14
1 b2 31
2 b2 7
2 b3 46
可是若是這時候還想按A列彙總且要C列的合計數,那就要再用兩個SQL來嵌套,很麻煩,不過用
rollup就簡單多了:
select nvl(col_a,'合計') col_a,nvl(col_b,decode(col_a,null,'','小計'||col_a))
col_b,sum(col_c)
from test_tbl group by rollup(col_a,col_b),結果以下
col_a col_b sum(col_c)
---- ----- --------
1 b1 14
1 b2 31
1 小計1 45
2 b2 7
2 b3 46
2 小計2 53
合計 98
結果集恰好是先按A和B彙總,而後是按A彙總,最後是所有彙總這時候若是再要按B列彙總,怎麼辦
呢?又要用SQL嵌套嗎?不是的,若是有這要求的話,改用cube函數就OK啦
select nvl(col_a,decode(col_b,null,'合計','小計'||col_b)) col_a,nvl(col_b,decode
(col_a,null,'','小計'||col_a)) col_b,sum(col_c)
from test_tbl group by cube(col_a,col_b) 結果以下
col_a col_b sum(col_c)
---- ----- --------
1 b1 14
1 b2 31
1 小計1 45
2 b2 7
2 b3 46
2 小計2 53
小計b1 b1 14
小計b2 b2 38
小計b3 b3 46
合計 98
跟剛纔rollup函數獲得的結果集有點不同,那就是多了些按B列的彙總行。
二、LAG和LEAD函數,自動連接上/下行記錄值
SQL> desc test_tbl
Name Type
----- ------
COL_K NUMBER
如今按順序的往這個test_tbl表中插入一系列數據,下面是SQL:
insert into test_tbl values(1)
insert into test_tbl values(2)
insert into test_tbl values(4)
insert into test_tbl values(5)
insert into test_tbl values(8)
insert into test_tbl values(9)
insert into test_tbl values(11)
insert into test_tbl values(12)
insert into test_tbl values(13)
........
數據插完後,要檢查插入的數據中,從最小數到最大數之間有那些數是沒被插入表,找出這些數的
前一個和後一個數?如這個例裏從1到13當中有目字三、六、七、10沒被插入表中,這些數的前一個和後一
個分別是2和四、5和八、9和11,即
PREV_VAL NEXT_VAL
---------- ----------
2 4
5 8
9 11
若是不用分析函數要獲得這後結果集那真不敢想象是怎麼樣的一段SQL,但用LAG分析函數那就簡單
了,這樣寫就OK
select prev_val,next_val from(
select col_k next_val,lag(col_k,1,0) over (order by col_k) prev_val from test_tbl
) where next_val-prev_val>1
對於LEAD函數是同樣的,只不過它是日後連接而已。
三、RANK和DENSE_RANK函數,對數據進行排名
測試表是這樣的select *from test_tbl結集以下
COL_A COL_B
---------- ----------
A 242
A 233
B 154
C 287
C 76
D 66
E 154
F 154
G 212
G 43
按A列來統計B列的值,用通常的SQL是這樣select col_a, sum(col_b) from test_tbl group by
col_a order by 2 desc 結果是這樣
COL_A SUM(COL_B)
---------- ----------
A 475
C 363
G 255
B 154
F 154
E 154
D 66
從這個數據集能夠看出A是最大的,C是第二大的,當數據多時就不知道誰是排第幾了,這時用
DENSE_RANK能夠達到這目的
select col_a,sum(col_b),dense_rank() over (order by sum(col_b) desc) ranks from
test_tbl group by col_a 結果以下
COL_A SUM(COL_B) RANKS
---------- ---------- ----------
A 475 1
C 363 2
G 255 3
B 154 4
F 154 4
E 154 4
D 66 5
這個數據集把每一個值都排了名次,能夠直接看得出,相同值的名次是相同的。
用RANK跟DENSE_RANK差很少,不過就是當出如今名次相同時,下一個名次會跳躍
select col_a,sum(col_b),rank() over (order by sum(col_b) desc ) ranks from test_tbl
group by col_a 結果以下
COL_A SUM(COL_B) RANKS
---------- ---------- ----------
A 475 1
C 363 2
G 255 3
B 154 4
F 154 4
E 154 4
D 66 7
能夠看到名次從4跳躍到7,就是由於名次4重複出現了兩次
實際應用中可能會比這些例子要複雜多點,可能會先對錶的數據分組,而後再用分析,如
select *from test_tbl的結果是這樣的
COL_G COL_A COL_B
---------- ---------- ----------
G1 A 242
G1 A 233
G2 C 287
G2 C 76
G2 D 66
G2 E 154
G3 F 154
G3 G 212
G3 G 43
G2 B 154
對這個數據集按G和A列彙總B列進行排名,就要先對錶按G列進行分組,而後再按A列彙總B列值進行
排名
select col_g,col_a,sum(col_b),dense_rank() over (partition by col_g order by sum
(col_b) desc ) ranks from test_tbl group by col_g,col_a這個SQL加了partition by先按G列分組,結果以下 COL_G COL_A SUM(COL_B) RANKS ---------- ---------- ---------- ---------- G1 A 475 1 G2 C 363 1 G2 B 154 2 G2 E 154 2 G2 D 66 3 G3 G 255 1 G3 F 154 2 能夠看到名次都是在G列的組別發生變化時,就會從新開始新排列 ;