Oracle的GROUP BY语句除了最基本的语法外,还支持ROLLUP和CUBE语句。

 rollup:

如果是ROLLUP(A, B, C)的话,首先会对(A、B、C)进行GROUP BY,然后对(A、B)进行GROUP BY,然后是(A)进行GROUP BY,最后对全表进行GROUP BY操作。

cube:

    如果是GROUP BY CUBE(A, B, C),则首先会对(A、B、C)进行GROUP BY,然后依次是(A、B),(A、C),(A),(B、C),(B),(C),最后对全表进行GROUP BY操作。

grouping:
    在使用rollup和cube函数时,可以结合grouping函数进行使用。
   1. grouping函数返回1时表示本条统计结果记录中该列未列入统计条件;返回值为0时表示该列被列入统计条件。

 2.使用 GROUPING 区分空值
  CUBE 操作所生成的空值带来一个问题:如何区分 CUBE 操作所生成的 NULL 值和从实际数据中返回的 NULL 值?这个问题可用 GROUPING 函数解决。如果列中的值来自事实数据,则 GROUPING 函数返回 0;如果列中的值是 CUBE 操作所生成的 NULL,则返回 1。在 CUBE 操作中,所生成的 NULL 代表全体值。可将 SELECT 语句写成使用 GROUPING 函数将所生成的 NULL 替换为字符串 ALL。因为事实数据中的 NULL 表明数据值未知,所以 SELECT 语句还可译码为返回字符串 UNKNOWN 替代来自事实数据的 NULL。例如:

SELECT CASE WHEN (GROUPING(Item) = 1) THEN 'ALL'
            ELSE ISNULL(Item, 'UNKNOWN')
       END AS Item,
       CASE WHEN (GROUPING(Color) = 1) THEN 'ALL'
            ELSE ISNULL(Color, 'UNKNOWN')
       END AS Color,
       SUM(Quantity) AS QtySum
FROM Inventory
GROUP BY Item, Color WITH CUBE

grouping_id: 

grouping_id()可以美化效果
 grouping_id()函数接受一列或多列统计条件,通过与having条件子句结合可以对统计记录进行过滤,将不包含小计或者总计的记录过滤掉,grouping_id()函数返回grouping()位向量的十进制值,GROUPING位向量的计算方法是将按照顺序对每一列调用GROUPING函数的结果组合起来。

GROUPING SETS

GROUPING SETS是对GROUP BY子句的进一步扩充。使用GROUPING SETS在同一个查询中定义多个分组集,Oracle对GROUPING SETS子句指定的分组集进行分组后用UNION ALL操作将各分组结果集结合起来,GROUPING SETS的优点是:只进行一次分组即可,不必书写复杂的UNION语句,GROUPING SETS中包含的分组项越多,性能越好。             

(4)复合列:是被作为整体处理的一组列的集合,如ROLLUP(a,(b,c))



(5)连接分组集

GROPU BY GROUPING SETS(a,b),GROPUING SETS(c,d)等价于:
GROUP BY (a,c)
UNION
GROUP BY (a,d)
UNION
GROUP BY (b,c)
UNION
GROUP BY (b,d)

GROUP BY department_id,ROLLUP(job_id),CUBE(manager_id)等价于:
(department_id,job_id,manager_id),(department_id,manager_id),(department_id,job_id),(department_id);

解释:

rollup(job_id)=(job_id,null),cube(manager_id)=(manager_id,null)所以GROPU BY department_id,ROLLUP(job_id),CUBE(manager_id)就等价于deparment_id*(job_id,null)*(manager_id,null)最后的结果为:
(department_id,job_id,manager_id),(department_id,null,manager_id),(department_id,job_id,null),(department_id,null,null)=>
(department_id,job_id,manager_id),(department_id,manager_id),(department_id,job_id),(department_id);