Reputation: 789
Student Subj Period Score
-------------------------
A Math 100 50
A Hist 100 100
A Sci 200 70
B Math 100 50
B Hist 100 50
I'm trying to query for the highest score for an each student.
If scores are all same (such as 'B' then pick one on the bottom. If that's not possible, just pick anything.
I'm having a hard time using max() and min() and group by to get a correct result. Result should look like this
Student Subj Period Score
-------------------------
A Hist 100 100
B Hist 100 50
Upvotes: 0
Views: 4787
Reputation: 130899
Gordon's answer certainly works very well, and it uses ANSI syntax that is supported by a number of database engines.
Oracle has an additional syntax that I don't think is ANSI, but it eliminates the need for any subquery. It performs at least as well as Gordon's answer (it may be slightly faster, but I'm not sure). It uses a KEEP LAST extension to aggregate functions.
select student,
max(subj) keep( dense_rank last order by score, period ) as subj,
max(period) keep( dense_rank last order by score, period ) as period,
max(score) as score
from grades
group by student
;
Note - Unless you explicitly want to provide random results, you should always structure your query to give determinate answers, meaning that a given set of data will always give the same answer, regardless how the data was loaded. I structured the above query to order by the highest score, followed by the highest period. If there is still a tie then the max(subj) is returned.
Upvotes: 1
Reputation: 1270653
You want to use analytic functions (I assume this is in Oracle from the mention of pl/sql):
select Student, Subj, Period, Score
from (select t.*,
row_number() over (partition by student order by score desc) as seqnum
from t
) t
where seqnum = 1
Upvotes: 2