GROUP_IDoracle
首先咱們看看官方的解釋:ide
大意是GROUP_ID用於區分相同分組標準的分組統計結果。函數
解釋起來比較抽象,下面咱們來看看具體的案例。spa
例1:單一分組code
SQL> select group_id(),deptno,sum(sal) from emp group by rollup(deptno); GROUP_ID() DEPTNO SUM(SAL) ---------- ---------- ---------- 0 10 8750 0 20 10875 0 30 9400 0 29025
rollup(deptno)只是一個惟一的分組,因此產生的group_id()爲0,表明這是同一個分組的結果。server
下面咱們來看看重複分組的狀況htm
例2:重複分組blog
SQL> select group_id(),deptno,sum(sal) from emp group by rollup(deptno,deptno); GROUP_ID() DEPTNO SUM(SAL) ---------- ---------- ---------- 0 10 8750 0 20 10875 0 30 9400 1 10 8750 1 20 10875 1 30 9400 0 29025 7 rows selected.
group_id()爲1表明這些是重複的分組。get
注意:可經過having group_id() <1來剔除重複的分組。it
老實說,我也看不出GROUP_ID在實際工做中的應用場景,姑且先記着。
GROUPING
其語法爲:GROUPING(expr)
下面咱們來看看官方的解釋:
即GROUPING函數用於區分分組後的普通行和聚合行。若是是聚合行,則返回1,反之,則是0。
下面咱們來看看具體的案例:
SQL> select grouping(deptno),grouping(job),deptno,job,sum(sal) from emp group by rollup(deptno,job); GROUPING(DEPTNO) GROUPING(JOB) DEPTNO JOB SUM(SAL) ---------------- ------------- ---------- --------- ---------- 0 0 10 CLERK 1300 0 0 10 MANAGER 2450 0 0 10 PRESIDENT 5000 0 1 10 8750 0 0 20 CLERK 1900 0 0 20 ANALYST 6000 0 0 20 MANAGER 2975 0 1 20 10875 0 0 30 CLERK 950 0 0 30 MANAGER 2850 0 0 30 SALESMAN 5600 0 1 30 9400 1 1 29025 13 rows selected.
首先咱們看GROUPING(DEPTNO)這一列的結果,不難看出,凡是基於DEPTNO的彙總,GROUPING的結果均爲0,由於最後一行是總的彙總,因此GROUPING的值爲1.
基於這個邏輯,能夠看出GROUPING(JOB)的值也是吻合的。
GROUPING_ID
GROUPING_ID是GROUPING的加強版,與GROUPING只能帶一個表達式不一樣,它能帶多個表達式。
語法以下:
GROUPING_ID(expr1, expr2, expr3,….)
下面咱們來看看官方的解釋:
GROUPING_ID在功能上至關於將多個GROUPING函數的結果串接成二進制數,返回的是這個二進制數對應的十進制數。
下面咱們來看看具體的案例:
SQL> select grouping(deptno)g_d,grouping(job)g_j,grouping_id(deptno)gi_d,grouping_id(job)gi_j,grouping_id(deptno,job)gi_dj,grouping_id(job,deptno)gi_jd,deptno,job,sum(sal) from emp group by cube(deptno,job); G_D G_J GI_D GI_J GI_DJ GI_JD DEPTNO JOB SUM(SAL) ---------- ---------- ---------- ---------- ---------- ---------- ---------- --------- ---------- 1 1 1 1 3 3 29025 1 0 1 0 2 1 CLERK 4150 1 0 1 0 2 1 ANALYST 6000 1 0 1 0 2 1 MANAGER 8275 1 0 1 0 2 1 SALESMAN 5600 1 0 1 0 2 1 PRESIDENT 5000 0 1 0 1 1 2 10 8750 0 0 0 0 0 0 10 CLERK 1300 0 0 0 0 0 0 10 MANAGER 2450 0 0 0 0 0 0 10 PRESIDENT 5000 0 1 0 1 1 2 20 10875 0 0 0 0 0 0 20 CLERK 1900 0 0 0 0 0 0 20 ANALYST 6000 0 0 0 0 0 0 20 MANAGER 2975 0 1 0 1 1 2 30 9400 0 0 0 0 0 0 30 CLERK 950 0 0 0 0 0 0 30 MANAGER 2850 0 0 0 0 0 0 30 SALESMAN 5600 18 rows selected.
你們看到這個案例估計都有點暈。。。
之因此這樣提供,是爲了呈現一個直觀的結果進行對比。
解讀這個結果,須要注意如下兩點:
1> 若本行是某expr的彙總,那麼該expr對應的二進制數位置爲0不然置爲1。
2> GROUPING_ID(expr1, expr2, expr3,….)的值實際上是對應GROUPING(expr1),GROUPING(expr2),GROUPING(expr3)...值的串接。
首先看第一列,第三列,雖然一個是grouping(deptno),一個是grouping_id(deptno),由於只有一個表達式,因此二者的結果是同樣的。第二列,第四列一樣如此。
第五列的結果是第一列和第二列的數值的串接,而後返回的十進制數,以第二行爲例,GI_DJ=2實際上是二進制10轉化爲十進制後的數,其中1爲G_D的值,0爲G_J的值。
而GI_JD=1則是二進制01轉化爲十進制後的數,其中0爲G_J的值,1爲G_D的值。注意,串接的順序爲GROUPING_ID中表達式的順序。
說了這麼多,下面咱們來看一個利用GROUPING_ID實現行列轉換的案例。
with t as ( select grouping_id(deptno,job)gi_dj,deptno,job,count(*)cnt from emp group by cube(deptno,job)), t1 as ( select decode(gi_dj,0,deptno,1,deptno,99) deptno,decode(gi_dj,1,cnt,3,cnt)sub_total, decode(job,'CLERK',cnt) c1,decode(job,'ANALYST',cnt)c2,decode(job,'MANAGER',cnt)c3, decode(job,'SALESMAN',cnt)c4,decode(job,'PRESIDENT',cnt)c5 from t) select deptno,max(sub_total) sub_total,max(c1)clerk,max(c2)analyst, max(c3)manager,max(c4)salesman,max(c5)president from t1 group by deptno order by deptno;
最後生成的結果以下:
DEPTNO SUB_TOTAL CLERK ANALYST MANAGER SALESMAN PRESIDENT ---------- ---------- ---------- --------- ---------- ---------- ---------- 10 3 1 1 1 20 5 2 2 1 30 6 1 1 4 99 14 4 2 3 4 1
其中,99表明合計,sub_total表明小計。這種統計類的需求在實際生產中仍是應用蠻廣的。
固然,該結果也可利用PIVOT函數實現,具體語句以下:
with t as(select grouping_id(deptno,job)gi_dj,deptno,job,count(*)cnt from emp group by cube(deptno,job)), t1 as (select decode(gi_dj,0,deptno,1,deptno,99)deptno,decode(gi_dj,0,job,2,job,9)job,cnt from t) select * from (select * from t1)pivot(sum(cnt)for job in ('9','CLERK','ANALYST','MANAGER','SALESMAN','PRESIDENT')) order by deptno;
參考資料:
1> http://docs.oracle.com/cd/E11882_01/server.112/e41084/functions070.htm#SQLRF00646
2> http://docs.oracle.com/cd/E11882_01/server.112/e41084/functions071.htm#SQLRF00647
3> http://docs.oracle.com/cd/E11882_01/server.112/e41084/functions072.htm#SQLRF00648