GROUP函數-GROUP_ID,GROUPING,GROUPING_ID

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

相關文章
相關標籤/搜索