I have two tables that looks like this:
Class Name Score Top
1 Amy 90 X
1 Ben 70 X
1 Chu 80 X
2 Don 60 X
2 Elf 65 X
2 Fez 75 X
2 Ges 35 X
2 Han 40 X
Class NumToppers
1 2
2 3
I want to find Top “NumToppers” from each class and accordingly update “Top” field:
Class Name Score Top
1 Amy 90 Y
1 Ben 70 N
1 Chu 80 Y
2 Don 60 Y
2 Elf 65 Y
2 Fez 75 Y
2 Ges 35 N
2 Han 40 N
I have 100s of “Classes” in my real data. So, although data looks toyish, no toy solutions please.
Referring to this excellent page on selecting the ‘greatest-n-per-group’, here’s the query I came up with. In retrospect it is basically identical to @BassamMehanni’s answer, except that there is no
ROW_NUMBER()function in MySQL.This assumes you have tables
classandtoppers.Solution:
Note: if you have a primary ID on the
classtable that isn’t the compound(Class,Name,Score)combination, use that instead for the join condition marked#@@.Explanation
Basically, this query:
classfrom top-to-bottom by score, within each class. That is, ranks each student within each class.classfor which therankis<= NumToppers, for each class.For step 1, see the following (from the link I referred you):
This looks through every row of
class(after by sorting by class and descending score) and sets therankto 1 if we’re on to a new class, or torank+1if we’re within the same class.For step 2, we do a JOIN with
toppersonclassand pick the topNumToppersrows for each class:Finally, we update on these conditions (step 3). However we have to do
UPDATE classexplicitly so we have to add in an extraJOINof step 2 withclass:If you have a primary ID on
classthat is preferrably not compound (ie a one-column ID) then join on that instead.