轉自:http://www.itpub.net/thread-1441751-1-1.html
Group by的語法
Select [filed1,fild2,]聚合函數(filed),
[Grouping(filed),]
[Grouping_id(filed1,filed2,…)]
From tablename
Where condition
[Group by {rollup|cube}(filed,filed2)]
[having condition]
[order by filed1]
一、基本用法:
(1)我們通過幾個例子來研究groupby的基本用法
創建測試表
SQL> create table sales(
2 empid number, --僱員ID
3 depid number, - -部門ID
4 area varchar(20), --區域
5 salenum number); --銷售額
表已創建。
SQL> insert into sales values(1,1,'china',10);
SQL> insert into sales values(2,1,'china',10);
SQL> insert into sales values(3,1,'china',10);
SQL> insert into sales values(3,1,'china',10);
SQL> insert into sales values(3,1,'china',10);
SQL> insert into sales values(1,1,'china',10);
SQL> insert into sales values(2,1,'china',10);
SQL> insert into sales values(4,2,'china',10);
SQL> insert into sales values(4,2,'china',10);
SQL> insert into sales values(5,3,'us',10);
SQL> insert into sales values(5,3,'us',10);
需求1,按部門統計銷售額 (簡單用法)
SQL> select depid,sum(salenum) from sales group by depid;
DEPID SUM(SALENUM)
---------- ------------
1 70
2 20
3 20
需求2,按部門統計銷售額,並且只顯示銷售總額小於30的部門及銷售額(使用having子句)
SQL> select depid,sum(salenum) totalnum from sales
group by depid
having sum(salenum) <30;
DEPID SUM(SALENUM)
---------- ------------
2 20
3 20
註解:需求2需要使用having字名,而且在子句中不能使用別名,必須使用在select語句中書寫的形式
(2)Where 和having的區別
Wheret和having子句都用來篩選數據,但是where是針對原數據進行篩選,而having子句只是針對彙總後的結果進行篩選,所以在需求二的例子中,想要對銷售總額進行過濾只能使用having子句
(3)使用order by 排序
SQL> select depid,sum(salenum) from sales group by depid;二、擴展用法:
DEPID SUM(SALENUM)
---------- ------------
1 70
2 20
3 20
注意觀察需求1的例子,depid是已經按照在depid升序排列的,這是因爲oracle在做聚合統計的時候會首先對字段進行排序,所以最終的結果是按 照升序進行排列的,如果order by後跟着多個字段,默認排序是先對第一個字段升序排序,然後再排第二個字段,以此類推,所以如果在應用中僅僅需要長序排序可以不用加order by 參數,畢竟這會影響性能
擴展用法使用下面的表進行實驗研究
SQL> create table testgroup(
2 a varchar(5),
3 b varchar(5),
4 c varchar(5),
5 n number);
建完測試表,然後插入兩條測試數據
SQL> insert into testgroup values('a1','b1','c1',10);
SQL> insert into testgroup values('a1','b1','c1',20);
我們使用基本的group by 可以得到以下結果
SQL> select a,b,c,sum(n) total from testgroup group by a,b,c;
A B C TOTAL
----- ----- ----- ----------
a1 b1 c1 30
(1)使用rollup操作符
Rollup意思有”捲起,彙總”的意思,他可以在使得在其括號中的字段,按從右到左的順序分別group後顯示,類似我們用多個group by 語句,然後union all起來,我們把針對上面的測試表,使用rollup操作符,看看效果(2)使用cube操作符
SQL> select a,b,c,sum(n) total from testgroup group by rollup(a,b,c);
Result:
從上面結果可以看出, 除了對(a1,b1,c1)進行了彙總外,又從右向左分別對子句中的”a,b,c”字段進行了彙總,例如(a1,b1),(a1) ()
A B C TOTAL a1 b1 c1 30 a1 b1 30 a1 30 30
Cube意思是立方,使用該操作符可以對操作符內的字段,進行遍歷組合彙總,例如cube(a,b,c),那麼就會產生8種組合結果,分別如下”a-b-c”,”a-b”,”a”,”a-c”,” b-c”,”b”,”c”,”空”,看下面的例子
SQL> select a,b,c,sum(n) total from testgroup group by cube(a,b,c);
Result:
(3),使用grouping(filed)函數
A B C TOTAL 30 c1 30 b1 30 b1 c1 30 a1 30 a1 c1 30 a1 b1 30 a1 b1 c1 30
使用grouping 函數必須先理解rollup 和cube操作符,那麼grouping函數有什麼用呢?在日常應用中,我們通過rollup或者cube對彙總進行了彙總,彙總後的結果往往要傳送到應 用程序端,在應用程序端我們必須要有一個依據來判斷某行數據是不是按照rollup或cube進行彙總,grouping函數可以用來產生這個依據,他可 以接收一個參數,判斷該參數是否爲null,是則返回1,否則返回0,我樣可以據此來判斷該是否按某列進行彙總統計的,當然在實驗應用中,0和1看起來不 那麼直觀,我們可以使用decode或者case函數進行轉議,讓查看結果看起來更直觀,請看以下例子(4)使用grouping_id(filed1,file2,…)函數
SQL> select grouping(a) ca,grouping(b) cb,grouping(c) cc, a,b,c,sum(n) from testgroup group by rollup(a,b,c);
Result:
CA CB CC A B C SUM(N) 0 0 0 a1 b1 c1 30 0 0 1 a1 b1 30 0 1 1 a1 30 1 1 1 30
使用grouping函數有時候感覺不是那麼靈活的,他只能接收一個字段,而grouping_id()函數則可以接收多個字 段,GROUPING_ID()函數可以接受一列或多列,返回按GROUPING位向量進行計算的十進制值。下面我們通過一個例子來研究 grouping_id函數是如何按照grouping函數的位向量進行計算的。
SQL> select grouping(a) ca,grouping(b) cb,grouping_id(a,b) caandb, a,b,sum(n) from testgroup group by rollup(a,b);
Result:
CA | CB | CAANDB | A | B | SUM(N) |
0 | 0 | 0 | a1 | b1 | 30 |
0 | 1 | 1 | a1 | 30 | |
1 | 1 | 3 | 30 |
位向量計算方法:如上例,
第一行,CA=0,CB=0,那麼位向量就是“00”,換算成十進制是0
第二行,CA=0,CB=1,那麼位向量就是‘01’,換算成十進制是1
第三行,CA=1,CB=1,那麼位向量就是‘11’,換算成十進制是3
請注意上例中grouping_id的計算值跟括號內的字段順序有關,上例中書寫順序是grouping_id(a,b),a字段在前面,如果換下順序grouping_id(b,a),計算結果是不一樣的,看下例
SQL> select grouping(a) ca,grouping(b) cb,grouping_id(b,a) caandb, a,b,sum(n) from testgroup group by rollup(a,b);
Result:
CA | CB | CAANDB | A | B | SUM(N) |
0 | 0 | 0 | a1 | b1 | 30 |
0 | 1 | 2 | a1 | 30 | |
1 | 1 | 3 | 30 |
看看第二行紅色字體,grouping_id中的字段順序發生了變化,位向量值也不一樣了
(4-1) grouping_id()函數的用途
上面講了grouping_id的用法,但在日常工作中,我們如何應用該函數呢?其實只要瞭解了他的原理及用法,要怎麼用,就看我們是否可以靈活使用了,下面介紹一種常見的用法:
假如我們要對某testgroup進行分組統計,並且過濾掉不包括小計或總計的行,這時grouping_id就有用武之地了,我們可以利用grouping_id的值結合having子句,通過判斷grouping_id是否大於0來過濾掉不需要的行。
SQL> select grouping(a) ca,grouping(b) cb,grouping_id(a,b) caandb, a,b,sum(n) from testgroup group by rollup(a,b) having grouping_id(a,b)>0;
Result:
CA | CB | CAANDB | A | B | SUM(N) |
0 | 1 | 1 | a1 | 30 | |
1 | 1 | 3 | 30 |