我正在尝试生成一份报告,告诉我每个科目每个学期每个字母的每个成绩的百分比。最终报告将主题代码(如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 >= 201230
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 >= 201230
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);
答案 0 :(得分: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 >= 201230
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 >= 201230
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中使用表别名,并注意循环。
谢谢。