学生收入管理系统中,系统按每学年生成一张费用详细表(如2009年系统会生成Fei_detail2009表);
现在需要统计一名学生从大学一年级到大学四年级的缴费情况。(设该生2005年入学)
那么需要从系统中Fei_detail2005表一直到Fei_detail2009表中去执行查询语句:
select max(termYear) termyear, uni_no, max(name) name, fcode, startyear,sum(samt) samt, sum(yamt) yamt,sum(tamt) tamt,sum(jamt) jamt,sum(samt-yamt+tamt-jamt) amt from fei_detail#  where TRIM(uni_no) = ? group by uni_no,startYear,fcode”//#表示年度
这样效率很低,因为一直Fei_detail#表中有数万条记录,且情况更糟的是,当需要查询的学生情况不确定时,如该生有过休学,或是留级,这时你将不知道从Fei_detail#那一年开始查询,最笨最保险的方法就是从系统中所有的Fei_detail#进行循环查询,再用程序(如java)将查询到的结果进行封装。
我在用java取Oracle数据时候就是这样,从数据库系统中从2002年一直循环到2009年,我的程序在查询一个学生缴费情况的时候大概需要5,6秒钟;
请教高手能否有办法提高查询的效率!

解决方案 »

  1.   

    先给你一个应急的办法,建个视图,把2002到2009年的数据都装入这张视图,像这样:create or replace view b as select t1.*from a1 t1 union all select t2.* from a2 t2;然后在视图上查询:
     select distinct t.uni_no,
                     t.fcode,
                     t.startyear,
                     max(termYear) over(partition by uni_no, startYear, fcode) as termyear,
                     max(name) over(partition by uni_no, startYear, fcode) as name,
                     sum(samt) over(partition by uni_no, startYear, fcode) as samt,
                     sum(yamt) over(partition by uni_no, startYear, fcode) as yamt,
                     sum(tamt) over(partition by uni_no, startYear, fcode) as tamt,
                     sum(jamt) over(partition by uni_no, startYear, fcode) as jamt
       from b t;这样做的缺点是明年你就得维护这个视图了,所以最好的方法是建个中间表,再建个存储过程,每年调用一次存储过程,把历年的数据存到中间表中,然后用这个查询查中间表就行了。你这个系统为什么要每年生成一张表呢?直接往原来的表插数据不行吗?这样设计简直太笨了。
      

  2.   

    这个TRIM必须加吗,如果没用就不用加了,要不然即使uni_no上有索引也用不上,
    如果非要去空格,建一个基于TRIM(uni_no)的函数索引。
    如create idx_detail_trno on fei_detail2001(trim(uni_no));