`
hypgr
  • 浏览: 273222 次
社区版块
存档分类
最新评论

利用Oracle内置分析函数进行高效统计汇总(2)

阅读更多

问题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。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics