Hier ist ein Weg, dies zu tun.
Das Problem ist kompliziert, weil - wie es scheint - Sie ALLE Eingangszeilen in der Ergebnismenge anzeigen möchten, aber dann sollten die verschiedenen Aggregate nur einige Zeilen berücksichtigen.
Der erste Teil ist einfach: Die Unterabfrage sortiert die Zeilen für jede Kombination von EMPLID
und COURSE_ID
in absteigender Reihenfolge der empfangenen Klasse und weist ihnen eine Zeilennummer (innerhalb der Gruppe) basierend auf dieser Reihenfolge zu.
Die äußere Abfrage führt die Aggregation durch. Ich benutze GROUP BY ROLLUP
, die viel Flexibilität erlaubt. Wenn das "Rollup" tatsächlich jede Zeile für sich ist, zeige ich die tatsächlichen Kreditstunden und Notenpunkte für diese Zeile, aber in den Aggregaten summiere ich über etwas anderes: nämlich über die Kreditstunden (und die Kreditstunden multipliziert mit Notenpunkten)) wenn die Zeilennummer 1 ist und andernfalls NULL
(was so behandelt wird, als ob es nicht existierte, als SUM()
berechnet wurde).
Ich habe einen zweiten Mitarbeiter erstellt, der zweimal die gleiche Punktzahl für den gleichen Kurs bekommen hat (damit ich überprüfen kann, dass meine Lösung in einem solchen Fall keine falschen Antworten liefert). Ich simuliere eine separate Tabelle für die Kreditstunden für jede Kurs-ID und den Join, der benötigt wird, um das im Ergebnis zu erhalten. Außerdem summiere ich keine Punkte, da dies nicht mit der Berechnung von Noten gemacht wird. Stattdessen verwende ich die korrekte Berechnung, bei der jeder Grad mit den Kursstunden multipliziert wird, und dann werden diese Produkte (nur für die höchste Note für jeden Kurs, separat für jeden EMPLID
) addiert.
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)
;
Ausgang:
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
OK. Was hast du probiert? – OldProgrammer
Quick question: Credit Stunden sind ein Merkmal eines Kurses, unabhängig von dem Studenten, der es nahm und dem Semester, in dem es gelehrt wurde. Wenn dies richtig ist (ich hatte eine ganze Karriere in der Wissenschaft), warum ist es eine Spalte in dieser Tabelle und nicht in einer separaten Tabelle mit Informationen über Kurse? – mathguy
@mathguy du hast ich erstellt nach meinem requirment. – saqib