Reputation: 1427
I have a database of student exam data similar to the database displayed below. I am trying to assign ranks
to these students by taking the sum of Marks
of all subjects(Subj
) for a semester(Sem
) and sorting them accordingly.
So if this is the raw db:
Name | S.NO.| Subj | Sem | Marks | Rank
ab | B1 | C1 | 1 | 002 |
ab | B1 | C2 | 1 | 004 |
ab | B1 | C3 | 1 | 005 |
ab | B1 | C4 | 2 | 008 |
xy | C2 | C1 | 1 | 006 |
xy | C2 | C2 | 1 | 004 |
xy | C2 | C3 | 2 | 007 |
xy | C2 | C4 | 2 | 009 |
xy | C2 | C5 | 2 | 003 |
sm | Z1 | C1 | 1 | 006 |
sm | Z1 | C2 | 2 | 004 |
sm | Z1 | C3 | 2 | 008 |
I would like to convert it into:
Name | S.NO.| Subj | Sem | Marks | Rank
ab | B1 | C1 | 1 | 002 | 1(coz his total is 11 in sem 1)
ab | B1 | C2 | 1 | 004 | 1
ab | B1 | C3 | 1 | 005 | 1
ab | B1 | C4 | 2 | 008 | 3
xy | C2 | C1 | 1 | 006 | 2
xy | C2 | C2 | 1 | 004 | 2
xy | C2 | C3 | 2 | 007 | 1(coz his total is 19 in Sem 2)
xy | C2 | C4 | 2 | 009 | 1
xy | C2 | C5 | 2 | 003 | 1
sm | Z1 | C1 | 1 | 006 | 3
sm | Z1 | C2 | 2 | 004 | 2
sm | Z1 | C3 | 2 | 008 | 2
The database has about 300k rows.
Upvotes: 0
Views: 87
Reputation: 8423
This is what you want
select name,sno,subj,sem,mark,rank
from
(
select e1.*
, @sm:=(select sum(e2.mark) from exams e2 where e1.name=e2.name and e1.sem=e2.sem) summark
, case when @sem!=sem then @r:=1
when @s !=@sm then @r:=@r+1
else @r
end as rank
, @s:=@sm
, @sem:=sem
from exams e1,(select @r:=0, @s:=0,@sm:=0,@sem:=0) r
order by sem,summark desc
) r2
order by sno,subj;
I do not know about the runtime. It maybe takes bit.
Demo on SQL Fiddle: http://sqlfiddle.com/#!9/b0290/1
To explain a bit the above. MySQL does not have analytical functions like other databases (e.g. Oracle). But the above simulates it. @sm
is the sum of the marks. @r
is the rank variable. It is increased if the marks sum changes. It is reset to 1 when semester changes. @s
saves the sum of previous row and @sem
saves the semester of the previous row.
Upvotes: 1