日期:2014-05-17  浏览次数:20779 次

变态的汇总统计需求
原表数据实例如下所示。
---------------------------
分公司 经营部 客户 市场级别 销售数量
北京分公司 北京经营部 客户01 一级市场 1
北京分公司 北京经营部 客户02 一级市场 1
北京分公司 北京经营部 客户03 二级市场 1
北京分公司 北京经营部 客户04 五级市场 1
上海分公司 上海经营部 客户01 一级市场 1
上海分公司 上海经营部 客户02 一级市场 1
上海分公司 上海经营部 客户03 二级市场 1
上海分公司 上海经营部 客户04 五级市场 1


怎么用一条sql查询得到下面的结果

分公司 经营部 客户 市场级别 销售数量
北京分公司 北京经营部 客户01 一级市场 1
北京分公司 北京经营部 客户02 一级市场 1
北京分公司 北京经营部 一级市场 2
北京分公司 北京经营部 客户03 二级市场 1
北京分公司 北京经营部 二级市场 1
北京分公司 北京经营部 客户04 五级市场 1
北京分公司 北京经营部 五级市场 1
北京分公司 北京经营部 4
北京分公司 一级市场 2
北京分公司 二级市场 1
北京分公司 五级市场 1
北京分公司 4
上海分公司 上海经营部 客户01 一级市场 1
上海分公司 上海经营部 客户02 一级市场 1
上海分公司 上海经营部 一级市场 2
上海分公司 上海经营部 客户03 二级市场 1
上海分公司 上海经营部 二级市场 1
上海分公司 上海经营部 客户04 五级市场 1
上海分公司 上海经营部 五级市场 1
上海分公司 上海经营部 4
上海分公司 一级市场 2
上海分公司 二级市场 1
上海分公司 五级市场 1
上海分公司 4
合计 一级市场 4
合计 二级市场 2
合计 五级市场 2
合计 8


------解决方案--------------------
CUBE()可以实现多维汇总

CUBE进行grouping列规定的grouping,创建所有可能的小计。在多维分析的术语中,CUBE生成CUBE数据规定维度的所有能计算的小记。
如果规定了CUBE(time,region,department),那么结果集将会包括相应rollup的所有值加上额外的合并。如果有n类在CUBE中规定,那么将会有2的n次方的小记返回。

When to Use CUBE
需要交叉报表的地方可以用Cube。交叉报表的数据生成可以通过简单的带有Cube的select查询语句实现。像Rollup,Cube在总结性报表中非常有用。Cube相比较一维多层,在多维的情况下更有用。
CUBE Syntax
CUBE出现在select语句的group by条款中。它的形式是:
Select … group by CUBE (group_column_reference_list)
例:
select channel_desc,
calendar_month_desc,
country_id,
sum(amount_sold) sales$
from sales,customers,times,channels
Where sales.time_id=times.time_id 
And sales.cust_id = customer.cust_id 
And sales.channel_id = channels.channel_id
And channels.channel_desc IN ( ‘direct sales’,’Internet’)
And times.calendar_month_desc IN (‘2000-09’,’2000-10’)
And country_id IN (‘UK’,’US’)
Group by CUBE (channel_desc,calendar_month_desc,country_id);
CHANNEL_DESC CALENDAR CO SALES$
-------------------- -------- -- --------------
Direct Sales 2000-09 UK 1,378,126
Direct Sales 2000-09 US 2,835,557
Direct Sales 2000-09 4,213,683
Direct Sales 2000-10 UK 1,388,051
Direct Sales 2000-10 US 2,908,706
Direct Sales 2000-10 4,296,757
Direct Sales UK 2,766,177
Direct Sales US 5,744,263
Direct Sales 8,510,440
Internet 2000-09 UK 911,739
Internet 2000-09 US 1,732,240
Internet 2000-09 2,643,979
Internet 2000-10 UK 876,571
Internet 2000-10 US 1,893,753
Internet 2000-10 2,770,324
Internet UK 1,788,310
Internet US 3,625,993
Internet 5,414,303
2000-09 UK 2,289,865
2000-09 US 4,567,797
2000-09 6,857,662
2000-10 UK 2,264,622
2000-10 US 4,802,459
2000-10 7,067,081
UK 4,554,487
US 9,370,256
13,924,743


------解决方案--------------------
这个是可以结合group的增强功能group by rollup,或者group by cube实现,但上述两个功能是oracle定制的为特定功能实现的。
简单看了一下,rollup和cube任何一个都不能独立完成上述需求,结合两者实现的话又需要较为谨慎的过滤。
实际上,楼主可以考虑采用更为灵活的grouping sets实现这个功能。
如下所示。

with t1 as
(
select '北京分公司' f1, '北京经营部' f2 ,'客户01' f3 ,'一级市场' f4,1 f5 from dual
union all
select '北京分公司' f1, '北京经营部' f2, '客户02' f3 ,'二级市场' f4,1 f5 from dual
union all
select '北京分公司' f1, '北京经营部' f2 ,'客户03' f3 ,'一级市场' f4,1 f5 from dual
union all
select '北京分公司' f1, '北京经营部' f2, '客户04' f3 ,'五级市场' f4,1 f5 from dual
union all
select '上海分公司' f1, '上海经营部' f2, '客户01' f3 ,'一级市场' f4,1 f5 from dual
union all
select '上海分公司' f1, '上海经营部' f2, '客户02' f3 ,'二级市场' f4,1 f5 from dual
union all
select '上海分公司' f1, '上海经营部' f2, '客户03' f3 ,'一级市场' f4,1 f5 from dual
union all
select '上海分公司' f1, '上海经营部' f2, '客户04' f3 ,'五级市场' f4,1 f5 from dual
)

select f1,f2,f4,f3,sum(f5)&