Tradycyjna metoda to analityczna
MAX()
(lub inna funkcja analityczna):
select *
from ( select s.student_id
, w.last_name
, w.first_name
, s.numeric_grade
, max(s.numeric_grade) over () as numeric_final_grade
from grade s
join section z
on s.section_id = z.section_id
join student w
on s.student_id = w.student_id
where z.course_no = 230
and z.section_id = 100
and s.grade_type_code = 'FI'
)
where numeric_grade = numeric_final_grade
Ale prawdopodobnie wolałbym używać PIERWSZY (ZACHOWAJ).
select max(s.student_id) keep (dense_rank first order by s.numeric_grade desc) as student_id
, max(w.last_name) keep (dense_rank first order by s.numeric_grade desc) as last_name
, max(w.first_name) keep (dense_rank first order by s.numeric_grade desc) as first_na,e
, max(s.numeric_grade_name) as numeric_final_grade
from grade s
join section z
on s.section_id = z.section_id
join student w
on s.student_id = w.student_id
where z.course_no = 230
and z.section_id = 100
and s.grade_type_code = 'FI'
Zaletą obu tych podejść w stosunku do tego, co początkowo sugerujesz, jest to, że skanujesz tabelę tylko raz, nie ma potrzeby uzyskiwania dostępu do tabeli lub indeksu po raz drugi. Gorąco polecam post na blogu Roba van Wijka o różnicach między nimi.
PS te zwrócą różne wyniki, więc są nieco inne. Funkcja analityczna zachowa duplikaty, jeśli dwóch uczniów ma ten sam maksymalny wynik (tak samo zrobi twoja sugestia). Funkcja agregująca usunie duplikaty, zwracając losowy rekord w przypadku remisu.