2017-08-01 3 views
0

Ich arbeite an einem Student Enrollment-Datenbank-Projekt. Die Schüler nehmen an Kursen teil und erhalten Noten. Manchmal wiederholt ein Student einen Kurs und bekommt eine bessere Note. Ich muss die Summe von grade_point und credit berechnen, indem ich nur die beste Note verwende. Also muss ich für jeden Studenten, der Kurse in verschiedenen Semestern wiederholt, bestimmen, was die höchste Note ist. emplid repräsentiert den Studenten, course_id identifiziert einen Kurs, credit ist natürlich credits hr, Grade_point ist der numerische Wert der Buchstabenklasse und term repräsentiert die Sitzung des Semesters.Max Grade_points für wiederholten Kurs von Student

Hier ist ein Beispiel für das, was ich erreichen möchte.

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 

Beispielcode von OP Kommentar:

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

OK. Was hast du probiert? – OldProgrammer

+0

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

+0

@mathguy du hast ich erstellt nach meinem requirment. – saqib

Antwort

-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

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 
+0

ja diese Logik funktioniert auch;) – saqib