2017-08-01 61 views
0

我正在参与学生注册数据库项目。学生参加课程并获得成绩。有时候学生会重复一门课程并获得更好的成绩。我只需要使用最好的等级来计算grade_point和credit的总和。所以对于重复不同学期课程的每个学生,我必须确定最高成绩是什么。 emplid代表学生,course_id代表课程,credit当然是学分hr,grade_point是字母等级的数字值,术语代表学期会话。学生重复课程的最高Grade_points

这是我正在努力完成的一个例子。从OP的评论

emplid couse_id credit_hr grade_pt term  
    0001 6001  3  4  Fall15 
    0001 6002  3  3.5  Fall15 
    0001 6003  3  2  Fall15 
    0001 6004  4  2.5  Sp16 
    0001 6002  3  3.0  Sp16 
total(requirrd)  13  12 

示例代码:

SELECT a.emplid 
     ,a.subject 
     ,a.CATALOG_NBR 
     ,a.strm 
     ,a.CRSE_GRADE_OFF 
     ,a.R‌​EPEAT_CANDIDATE 
     ,a.un‌​t_taken AS cr 
     ,a.CRSE_ID 
     ,MAX(a.grade_points) 
OVER (PARTITION BY A.emplid ,crse_id) 
FROM ps_CLASS_TBL_SE_VW a 
WHERE emplid LIKE '06381313011%' 
+1

确定。你有什么尝试? – OldProgrammer

+0

快速提问:学分课程是学习时间的一个特点,无论学生是谁,也不管学期是在哪里学习的。如果这是正确的(我的整个职业生涯都是在学术界),那么为什么它是本表中的专栏,而不是单独的表格中提供有关课程的信息? – mathguy

+0

@mathguy你对我创建视图根据我的需求。 – saqib

回答

-1

select emplid, sum(credit_hr), sum(grade_pt) 
 
from (
 
select emplid, course_id, credit_hr, grade_pt, term, 
 
row_number() over(partition by emplid, course_id 
 
order by grade_pt desc) rn 
 
from your_table 
 
) 
 
where rn = 1 
 
group by emplid

3

下面是做到这一点的方法之一。

问题很复杂,因为 - 看起来 - 您想要在结果集中显示所有输入行,但各种聚合应该只考虑一些行。

第一部分很简单:子查询按照接收等级的降序对EMPLIDCOURSE_ID的每个组合的行进行排序,并根据该顺序为它们分配一个行号(在组内)。

外部查询执行聚合。我使用GROUP BY ROLLUP,这允许很大的灵活性。当“汇总”实际上是每一行本身时,我会显示该行的实际信用小时数和等级点数,但是在总计中,我总结了其他一些信息:即在信用时间(以及信用小时乘以等级点数)当行号为1时,以及NULL,否则(在计算SUM()时将其视为不存在)。

我创建了第二个员工,他在同一个课程中获得了两次相同的分数(所以我可以检查我的解决方案在这种情况下不会给出错误答案)。我为每个课程ID的学分模拟了一个单独的表格,并且在结果中需要连接。另外,我不总结分数点数,因为这不是用分数点计算完成的;相反,我使用正确的计算方法,每个成绩点乘以课程时数,然后将这些产品(仅适用于每门课程的最高成绩,各自分别为EMPLID)加在一起。

with 
    grades (emplid, course_id, grade_pt, term) as (
     select '0001', '6001', 4 , 'Fall15' from dual union all 
     select '0001', '6002', 3.5, 'Fall15' from dual union all 
     select '0001', '6003', 2 , 'Fall15' from dual union all 
     select '0001', '6004', 2.5, 'Sp16' from dual union all 
     select '0001', '6002', 3 , 'Sp16' from dual union all 
     select '0003', '6002', 3.5, 'Sp16' from dual union all 
     select '0003', '6003', 2.5, 'Fall16' from dual union all 
     select '0003', '6003', 2.5, 'Sp15' from dual 
    ), 
    credits (course_id, credit_hr) as (
     select '6001', 3 from dual union all 
     select '6002', 3 from dual union all 
     select '6003', 3 from dual union all 
     select '6004', 4 from dual 
    ) 
-- End of simulated inputs (for testing purposes only, not part of the solution). 
-- SQL query begins BELOW THIS LINE. 
select emplid, course_id, 
     case when grouping(term) = 0 then credit_hr 
      else sum(case when rn = 1 then credit_hr end) end as credit_hr, 
     case when grouping(term) = 0 then grade_pt 
      else sum(case when rn = 1 then credit_hr * grade_pt end) 
                  end as total_grade_pt, 
     term 
from (select g.emplid, g.course_id, c.credit_hr, g.grade_pt, g.term, 
       row_number() over (partition by g.emplid, g.course_id 
            order by g.grade_pt desc) as rn 
     from grades g join credits c on g.course_id = c.course_id 
     ) 
group by rollup(emplid, course_id, credit_hr, grade_pt, term) 
having grouping(term) = 0 or (grouping(course_id) = 1 and grouping(emplid) = 0) 
; 

输出

EMPLID COURSE_ID CREDIT_HR TOTAL_GRADE_PT TERM 
------ --------- --------- -------------- ------ 
0001 6001    3    4 Fall15 
0001 6002    3    3 Sp16 
0001 6002    3    3.5 Fall15 
0001 6003    3    2 Fall15 
0001 6004    4    2.5 Sp16 
0001      13   38.5 
0003 6002    3    3.5 Sp16 
0003 6003    3    2.5 Sp15 
0003 6003    3    2.5 Fall16 
0003      6    18 
+0

是的,这个逻辑也有效;) – saqib