第8章 SQL高级处理:8-2 GROUPING运算符
● 只使用GROUP BY子句和聚合函数是无法同时得出小计和合计的。如果想要同时得到,可以使用GROUPING运算符。
● 理解GROUPING运算符中CUBE的关键在于形成“积木搭建出的立方体”的印象。
● 虽然GROUPING运算符是标准SQL的功能,但还是有些DBMS尚未支持这一功能。
■ 同时计算出合计行
虽然这是按照商品种类计算销售单价的总额时得到的结果,但问题在于最上面多出了 1 行合计行。
使用代码清单 8-10 中的 GROUP BY 子句的语法无法得到这一行。
按照通常的思路,想一次得到这两种结果是不可能的。
如果想要获得那样的结果,通常的做法是分别计算出合计行和按照商品种类进行汇总的结果,然后通过 UNION ALLA 连接在一起(代码清单8-11)
这样一来,为了得到想要的结果,需要执行两次几乎相同的 SELECT语句,再将其结果进行连接,不但看上去十分繁琐,而且 DBMS 内部的
处理成本也非常高,难道没有更合适的实现方法了吗?
GROUPING 运算符包含以下 3 种。
●ROLLUP
●CUBE
●GROUPING SETS
目前 MySQL 仅支持ROLLUP
■ ROLLUP——同时得出合计和小计
■ ROLLUP的使用方法
■ 将“登记日期”添加到聚合键当中
在上述 GROUP BY 子句中使用 ROLLUP 之后,结果会发生什么变化呢?
将上述两个结果进行比较后我们发现,使用 ROLLUP 时多出了最上方的合计行以及 3 条不同商品种类的小计行。这 4 行就是我们所说的超级分组记录。
ROLLUP 是“卷起”的意思,可以同时得出合计和小计,是非常方便的工具。
■ GROUPING函数——让NULL更加容易分辨
为了避免混淆, SQL 提供了一个用来判断超级分组记录的 NULL 的特定函数 —— GROUPING 函数。该函数在其参数列的值为
超级分组记录所产生的 NULL 时返回 1,其他情况返回 0(代码清单 8-15)
这样就能分辨超级分组记录中的 NULL 和原始数据本身的 NULL 了。
使用 GROUPING 函数还能在超级分组记录的键值中插入字符串。也就是说,当 GROUPING 函数的返回值为 1 时,指定“合计”或者“小计”等字符串,其他情况返回通常的列的值。
在实际业务中需要获取包含合计或者小计的汇总结果(这种情况是最多的)时,就可以使用 ROLLUP 和 GROUPING 函数来实现了。
■ CUBE——用数据来搭积木
CUBE 是“立方体”的意思,这个名字和 ROLLUP 一样,都能形象地说明函数的动作。
CUBE 的语法和 ROLLUP 相同,只需要将 ROLLUP 替换为 CUBE 就可以了。
与 ROLLUP 的结果相比, CUBE 的结果中多出了几行记录。大家看一下应该就明白了,多出来的记录就是只把 regist_date 作为聚合键所得到的汇总结果。
所谓 CUBE,就是将 GROUP BY 子句中聚合键的“所有可能的组合”的汇总结果集中到一个结果中。
因此,组合的个数就是 2^n(n 是聚合键的个数)。
顺带说一下, ROLLUP的结果一定包含在CUBE的结果之中。使用ROLLUP 时组合的个数是n + 1。
■ GROUPING SETS——取得期望的积木
最后要介绍的 GROUPING 运算符是 GROUPING SETS。该运算符可以用于从 ROLLUP 或者 CUBE 的结果中取出部分记录。
使用 GROUPING SETS 的机会也就很少了。