问题5 求按登记注册类型多个层次划分的单位个数小计和总计
例如要得出如下的结果:
代码 登记注册类型 家数
------ --------------------------------------- ---------
100 内资企业 61920
110 国有企业 1365
140 联营企业 476
141 国有联营企业 52
...
200 港、澳、台商投资企业 9004
210 合资经营企业(港或澳、台资) 4454
220 合作经营企业(港或澳、台资) 556
300 外商投资企业 11396
310 中外合资经营企业 5070
320 中外合作经营企业 663
我们有3种方法,都可以完成任务。
方法1
select code 代码 , substrb(' ',1,item_level*2-2)||b.reg_type 登记注册类型, cnt 家数 from
(
(select substr(z01_08,1,1)||'00' code ,count(*) cnt
from cj601
group by substr(z01_08,1,1))
union
(select substr(z01_08,1,2)||'0' code ,count(*) cnt
from cj601
group by substr(z01_08,1,2))
union
(select substr(z01_08,1,3) code ,count(*) cnt
from cj601
group by substr(z01_08,1,3))
)
c, djzclx b where c.code=b.reg_code;
方法2
select code 代码 , substrb(' ',1,item_level*2-2)||b.reg_type 登记注册类型, cnt 家数 from
(
select
case when code3 is not null then code3
when code2<>'0' then code2
else code1
end code,cnt from (
select substr(z01_08,1,1)||'00' code1 , substr(z01_08,1,2)||'0' code2 , substr(z01_08,1,3) code3 ,count(*) cnt
from cj601
group by rollup(substr(z01_08,1,1),substr(z01_08,1,2),substr(z01_08,1,3))
) where code2<>code3 or code3 is null and code1<>'00'
)
c, djzclx b where c.code=b.reg_code
order by 1
;
方法3
select code 代码 , substrb(' ',1,item_level*2-2)||b.reg_type 登记注册类型, cnt 家数 from
(
select
case when code3 is not null then code3
when code2<>'0' then code2
else code1
end code,cnt from (
select substr(z01_08,1,1)||'00' code1 , substr(z01_08,1,2)||'0' code2 , substr(z01_08,1,3) code3 ,sum(cnt) cnt
from (select substr(z01_08,1,3) z01_08,count(*) cnt from cj601 group by substr(z01_08,1,3))
group by rollup(substr(z01_08,1,1),substr(z01_08,1,2),substr(z01_08,1,3))
) where code2<>code3 or code3 is null and code1<>'00'
)
c, djzclx b where c.code=b.reg_code
order by 1
;
上述3种写法都能得出正确的结果,但执行效率有巨大差别,第一种写法最简单,但是使用union要对cj601作了3遍全表扫描,执行效率最低,第2种写法对cj601做rollup分组,让数据库自动求小计和总计,第3种写法先对cj601做分组汇总,对结果集再做rollup分组,让数据库求小计和总计,在数据量中等的时候效率差不多,数据量大的时候,方法3效率更好些,因为rollup分组要处理的记录数更少,而rollup分组比普通分组开销大一些。
Oracle提供的分析函数一共有10多个,但有些专门的统计函数比如求标准差,相关系数,协方差等我们一般用不到,主要用到的是本文提到的RANK, lead, ratio_to_report等,我们如果能够将它们和decode函数,case语句配合,善加利用,就能编写出执行效率高的汇总语句,高效完成统计数据处理任务。更加详细的关于分析函数的信息,请参考资料Oracle9i Data Warehousing Guide 第19章SQL for Analysis in Data Warehouses。