jaisonDavis
jaisonDavis

Reputation: 1427

MySQL order table by taking the sum of one colomn for groups of values

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

Answers (1)

hol
hol

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. @smis 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

Related Questions