GROUP函數-GROUP_ID,GROUPING,GROUPING_ID


GROUP_ID

首先我們看看官方的解釋:

大意是GROUP_ID用於區分相同分組標准的分組統計結果。

解釋起來比較抽象,下面我們來看看具體的案例。

例1:單一分組

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,代表這是同一個分組的結果。

下面我們來看看重復分組的情況

例2:重復分組

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代表這些是重復的分組。

注意:可通過having group_id() <1來剔除重復的分組。

老實說,我也看不出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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM