2014-09-11 72 views
0

我正在尝试生成一份报告,其中给出了每个科目每个学期每个科目的每个等级的百分比。最终报告将MAT,ENC等主题代码作为行标题,然后将条目和字母等级作为列标题。我目前正在循环每个科目,然后每个学期,然后每个年级,需要2个小时才能完成。什么是完成这个的正确/更有效的方法。随意问你是否有任何问题。谢谢你的帮助!!过程需要几个小时才能完成

v_subj   varchar2(5); 
v_grade   varchar2(5); 
v_termloop  varchar2(6); 
c_total   number; 
c_dfw   number; 
c_gradetotal number; 
c_gradedfw  number; 
v_output varchar2(1000); 


Cursor Get_Terms is 
select distinct ssbsect_term_code from ssbsect 
where ssbsect_term_code >= 2
and ssbsect_term_code not like '%5' 
order by 1; 

Cursor Get_Subj is 
Select distinct ssbsect_subj_code from ssbsect 
where ssbsect_term_code >= 2
and ssbsect_insm_code = 'DL' 
and ssbsect_term_code not like '%5' 
order by 1; 

Cursor Get_Grade is 
select distinct msvcrse_grde_code from msvcrse 
where msvcrse_grde_code in ('A','B','C','D','F','S','U','W') 
order by 1; 

Cursor Get_Total is 
select count(msvcrse_pidm) from msvcrse 
join ssbsect on msvcrse_crn = ssbsect_crn 
          and msvcrse_Term_code = ssbsect_term_code 
where msvcrse_term_code = v_termloop 
and ssbsect_insm_code = 'DL' 
and msvcrse_crse_numb < '3000' 
and msvcrse_subj_code = v_subj 
and msvcrse_gmod_code <> 'D'; 

Cursor Get_GradeTotal is 
select count(msvcrse_pidm) from msvcrse 
join ssbsect on msvcrse_crn = ssbsect_crn 
          and msvcrse_Term_code = ssbsect_term_code 
where msvcrse_term_code = v_termloop 
and ssbsect_insm_code = 'DL' 
and msvcrse_grde_code like '%'||v_grade||'%' 
and msvcrse_crse_numb < '3000' 
and msvcrse_subj_code = v_subj 
and msvcrse_gmod_code <> 'D'; 


Begin 

Open Get_Subj; 
    Loop 
    Fetch Get_Subj into v_subj; 
    Exit when Get_Subj%NOTFOUND; 
    v_output := ''; 

    v_output := v_subj; 

    Open Get_Terms; 
     Loop 
     Fetch Get_Terms into v_termloop; 
     Exit when Get_Terms%NOTFOUND; 


     Open Get_Grade; 
      Loop 
      Fetch Get_Grade into v_grade; 
      Exit when Get_grade%NOTFOUND; 


      Open Get_Total; 
      Fetch Get_Total into c_total; 
      Close Get_Total; 


      Open Get_GradeTotal; 
      Fetch Get_GradeTotal into c_gradetotal; 
      Close Get_GradeTotal; 

      if c_total = 0 then 
       c_total := NULL; 
      end if; 

      v_output := v_output ||'|'||nvl(100*(round(c_gradetotal/c_total,3)),0); 

      --dbms_output.put_line(v_subj||'|'||v_termloop||'|'||v_insm||'|'||nvl(100*(round(c_dfw/c_total,3)),0)); 



      End Loop; 
     Close Get_Grade; 

     End Loop; 
    Close Get_Terms; 

    dbms_output.put_line(v_output); 
+1

你完全可以将它作为一个查询来完成,它比循环要快很多。但是,如果没有样本数据和表格结构,很难向您解释如何去做。 – 2014-09-11 13:10:09

+0

你想知道什么?这里唯一重要的表格是msvcrse,它是一个课程历史表。它为每个学生提供了他们参加的年级和学期代码的入学条目。这是否有帮助?感谢您的输入!! – 2014-09-11 13:14:38

回答

0

我改变了一点点你的代码,但结果应该是一样的。

请合并游标get_grade和get_gradetotal,在这段代码中没有任何意义。

DECLARE 
    c_total  NUMBER; 
    v_output  VARCHAR2 (1000); 


    CURSOR get_subj IS 
     SELECT DISTINCT ssbsect_subj_code 
     FROM ssbsect 
     WHERE ssbsect_term_code >= 2
     AND ssbsect_insm_code = 'DL' 
     AND ssbsect_term_code NOT LIKE '%5' 
    ORDER BY 1; 

    CURSOR get_terms IS 
     SELECT DISTINCT ssbsect_term_code 
     FROM ssbsect 
     WHERE ssbsect_term_code >= 2
     AND ssbsect_term_code NOT LIKE '%5' 
    ORDER BY 1; 

    CURSOR get_total (lci_termloop IN ssbsect.msvcrse_term_code%TYPE 
        , lci_subj  IN msvcrse.msvcrse_subj_code%TYPE) IS 
    SELECT COUNT (msvcrse_pidm) 
     FROM msvcrse 
      JOIN ssbsect 
      ON msvcrse_crn = ssbsect_crn 
      AND msvcrse_term_code = ssbsect_term_code 
    WHERE msvcrse_term_code = lci_termloop 
     AND ssbsect_insm_code = 'DL' 
     AND msvcrse_crse_numb < '3000' 
     AND msvcrse_subj_code = lci_subj 
     AND msvcrse_gmod_code <> 'D'; 

    CURSOR get_grade IS 
     SELECT DISTINCT msvcrse_grde_code 
     FROM msvcrse 
     WHERE msvcrse_grde_code IN ('A', 'B', 'C', 'D', 'F', 'S', 'U', 'W') 
    ORDER BY 1; 

    CURSOR get_gradetotal (lci_termloop IN ssbsect.msvcrse_term_code%TYPE 
         , lci_grade IN msvcrse.msvcrse_grde_code%TYPE 
         , lci_subj  IN msvcrse.msvcrse_subj_code%TYPE) IS 
    SELECT COUNT (msvcrse_pidm) AS msvcrse_pidm 
     FROM msvcrse 
      JOIN ssbsect 
      ON msvcrse_crn = ssbsect_crn 
      AND msvcrse_term_code = ssbsect_term_code 
    WHERE msvcrse_term_code = lci_termloop 
     AND ssbsect_insm_code = 'DL' 
     AND msvcrse_grde_code LIKE '%' || lci_grade || '%' 
     AND msvcrse_crse_numb < '3000' 
     AND msvcrse_subj_code = lci_subj 
     AND msvcrse_gmod_code <> 'D'; 
BEGIN 

    FOR rec_subj IN get_subj LOOP 
    v_output := rec_subj.ssbsect_subj_code; 

    FOR rec_term IN get_terms LOOP 

     OPEN get_total (lci_termloop => rec_term.ssbsect_term_code 
        , lci_subj  => rec_subj.ssbsect_subj_code); 
     FETCH get_total INTO c_total; 
     CLOSE get_total; 

     FOR rec_grade IN get_grade LOOP 
     <<grade_total>> 
     FOR rec_gradetotal IN get_gradetotal (lci_termloop => rec_term.ssbsect_term_code 
              , lci_grade => rec_grade.msvcrse_grde_code 
              , lci_subj  => v_output) LOOP 
      IF c_total = 0 THEN 
      c_total := NULL; 
      v_output := v_output || '|'; 
      CONTINUE grade_total; -- <-- AVOID WORK 
      END IF; 

      v_output := v_output || '|' || NVL (100 * (ROUND (rec_gradetotal.msvcrse_pidm/c_total, 3)), 0); -- <-- PLEASE MAKE THIS CODE BETTER 
      --dbms_output.put_line(rec_subj.ssbsect_subj_code||'|'||rec_term.ssbsect_term_code||'|'||v_insm||'|'||nvl(100*(round(c_dfw/c_total,3)),0)); 
     END LOOP grade_total; 
     END LOOP; 
    END LOOP; 

    --DBMS_OUTPUT.put_line (rec_subj.ssbsect_subj_code); 
    END LOOP; 

END; 

我改变所有的代码而没有编译,请确保游标中使用的类型。

我猜50%的改善,但你需要测试。

让我知道您是否有任何问题,请在SQL中使用表别名,并小心循环。

谢谢。

相关问题