只使用group by子句和聚合函数是无法同时得出小计和合计的,想要同时得到,可以使用grouping运算符。
同时得到合计行
使用group by 只能得到每组的合计值,不能得到总计:
select product_type, sum(sale_price)
from Product
group by product_type;
通常计算合计是分别计算出合计行和按照商品种类进行汇总的结果,然后通过union all连接在一起:
select '合计' as product_type, sum(sale_price)
from Product
union all
select product_type, sum(sale_price)
from Product
group by product_type;
rollup:同时得出合计和小计
grouping运算符包含以下3种:1.rollup
2.cube
3.grouping sets
rollup的使用方法:
select product_type, sum(sale_price) as sum_price
from Product
group by rollup(product_type);
多出来的一行就是所有的合计。
该运算符的作用,就是一次计算出不同聚合键组合的结果。使用rollup其实进行了如下两种组合的汇总结果:
1.group by()用来计算所有的总和
2.group by(product_type)用来分组计算总和
1中的group by()表示没有聚合键,也就相当于没有group by子句(这时会得到全部数据的合计行记录),该合计行记录称为超级分组记录。
将登记日期添加到聚合键中:
select product_type, regist_date, sum(sale_price) as sum_price
from Product
group by rollup(product_type, regist_date);
使用rollup时多出了最上方的合计行以及3条不同商品种类的小计行(也就是未使用登记日期作为聚合键的记录),这4行就是超级分组记录。
相当于3种聚合:1.group by()
2.group by(product_type)
3.group by(product_type, regist_date)
grouping函数:让null更加容易分辨
为了避免混淆null值,sql提供了grouping函数来判断超级记录分组记录的null。该函数在其参数列的值为超级分组记录所产生的null时返回1,其他情况返回0.
select grouping(product_type) as product_type, grouping(regist_date) as regist_date, sum(sale_price) as sum_price
from Product
group by rollup(product_type, regist_date);
在超级记录分组记录的键值中插入恰当的字符串:
select case when grouping(product_type) = 1
then '商品种类 合计'
else product_type end as product_type,
case when grouping(regist_date) = 1
then '登记日期 合计'
else cast(regist_date as varchar(16)) end as regist_date,
sum(sale_price) as sum_price
from Product
group by rollup(product_type, regist_date);
这里需要注意的是,由于cast表达式所有分支的返回值必须一致,所以要将日期转换为字符串。
cube:用数据来搭积木
select case when grouping(product_type) = 1
then '商品种类 合计'
else product_type end as product_type,
case when grouping(regist_date) = 1
then '登记日期 合计'
else cast(regist_date as varchar(16)) end as regist_date,
sum(sale_price) as sum_price
from Product
group by cube(product_type, regist_date);
这里的cube按以下4种方式聚合:1.group by()
2.group by(product_type)
3.group by(regist_date)
4.group by(product_type, regist_date)
所谓cube,就是将group by子句中的聚合键的所有可能的组合的汇总结果集中到一个结果中。因此,组合的个数就是2的n次方(n为聚合键的个数)。
grouping sets:取得期望的意思
select case when grouping(product_type) = 1
then '商品种类 合计'
else product_type end as product_type,
case when grouping(regist_date) = 1
then '登记日期 合计'
else cast(regist_date as varchar(16)) end as regist_date,
sum(sale_price) as sum_price
from Product
group by grouping sets(product_type, regist_date);
grouping sets用于从中取出个别条件对应的不固定结果(不常用)