7

I have a very simple MySQL table where I save subjects with Exam and CA Scores for each students with their admin_no. It looks like that:

 admin_no   subject     ca  exam    year       class_s 
10/00182     IRS        39  56    2014/2015     Grade 2
10/00177    English     39  59    2014/2015     Grade 2
10/00177    Mathematics 34  59    2014/2015     Grade 2
10/00177    Basic       37  59    2014/2015     Grade 2
10/00177    Social      39  60    2014/2015     Grade 2
10/00177    Yoruba      33  59    2014/2015     Grade 2
09/00159    English     37  59    2014/2015     Grade 2
09/00159    Mathematics 35  60    2014/2015     Grade 2
09/00159    Basic       39  59    2014/2015     Grade 2
.......................................................

I used the mysql query bellow to sum but exam scores and CA of all the subjects and then total all the scores of each students as total_scores and then rank the total scores:

SELECT admin_no,rank,total_score
FROM (SELECT *,  IF(@marks=(@marks:=total_score), @auto, @auto:=@auto+1) AS rank 
FROM (SELECT * FROM 
  (SELECT admin_no, SUM(exam)+SUM(ca) AS total_score,year,class_s
    FROM subjects_1 ,
    (SELECT @auto:=0, @marks:=0) as init WHERE `class_s`='Grade 2' and `year`='2014/2015'
     GROUP BY admin_no ) sub ORDER BY total_score DESC)t) as result 

The Output of the query:

 admin_no   rank total_score    
08/00076    1   1615
10/00170    2   1613
12/00300    3   1609
09/00091    4   1604
10/00182    5   1600
09/00159    6   1583
10/00177    7   1574
09/00152    8   1561
09/00165    9   1540
10/00176    10  1516
13/00354    11  1497
10/00178    12  1470
14/00348    13  1409
**14/00346  14  12
15/00371    14  12
09/00156    15  7**

Problems:The out put is good but having problem with tallies in the last three ranks .i.e the total scores 12 appear twice for 14/00346 and 15/00371 and they were given the same rank which is good but next to 12 is 7 and it is ranked 15 instead of 17. Pls help me I dont want the Rank to be consecutive if their is ties in the total_scores .

Bellow is a copy of my mysql data http://youth-arena.com/portal/sql.sql

Here are the php query codes

http://youth-arena.com/portal/query.txt

Mustofa Rizwan
  • 10,215
  • 2
  • 28
  • 43
Hamzat Luqman
  • 69
  • 1
  • 10
  • If I understand correctly, you're wanting to increment the rank (even if tied)? If so you should be able to do this by removing the `IF` statement and call only `@auto:=@auto+1`. The only problem, is that how do you decide who gets rank 14 and rank 15? MySQL would try to work this out for you, but the results could be intermittent. – ash Jul 26 '15 at 07:34
  • @jeroen Thank you so much, I removed the if statement and used this : SELECT admin_no,rank,total_score FROM (SELECT *, @auto:=@auto+1 AS rank FROM (SELECT * FROM (SELECT admin_no, SUM(exam)+SUM(ca) AS total_score,year,class_s FROM subjects_1 , (SELECT @auto:=0, @marks:=0) as init WHERE `class_s`='Grade 2' and `year`='2014/2015' GROUP BY admin_no ) sub ORDER BY total_score DESC)t) as result
    Thus, take me to another problem level as you have mentioned which is giving different ranks to the same total score.Pls help me with a complete code to work on this.Thanks
    – Hamzat Luqman Jul 26 '15 at 07:50
  • doublesidedstickytape thank you sir, pls am still waiting for how to get the ranking correctly with this script – Hamzat Luqman Jul 26 '15 at 19:36
  • Sorry Hsmzat, I am away from home at the moment. Good to oboe you have this working (almost) - what else is a deciding factor for determining who gets the higher rank when the total score is tied (If anything)? – ash Jul 26 '15 at 20:04
  • I asked a question not so long ago regarding the correct way to do ranking in MySQL - does this help? http://stackoverflow.com/a/24953537/1266457 – ash Jul 26 '15 at 20:09
  • Thanks, i have went through the post, and I still dont get the script worked as I expect. SELECT admin_no,rank,total_score FROM (SELECT *, @auto:=@auto+1 AS rank FROM (SELECT * FROM (SELECT admin_no, SUM(exam)+SUM(ca) AS total_score,year,class_s FROM subjects_1 , (SELECT @auto:=0, @marks:=0) as init WHERE `class_s`='Grade 2' and `year`='2014/2015' GROUP BY admin_no ) sub ORDER BY total_score DESC)t) as result – Hamzat Luqman Jul 27 '15 at 16:04
  • The Output is : admin_no rank total_score Descending 1 08/00076 1 1615 10/00170 2 1613 12/00300 3 1609 09/00091 4 1604 10/00182 5 1600 09/00159 6 1583 10/00177 7 1574 09/00152 8 1561 09/00165 9 1540 10/00176 10 1516 13/00354 11 1497 10/00178 12 1470 14/00348 13 1409 14/00346 14 12 15/00371 15 12 09/00156 16 7 – Hamzat Luqman Jul 27 '15 at 16:06
  • OK - I've managed to get a MySQL setup while I am away - can you provide more (desensitised) data to your question please as an edit in your question so I can replicate the rank issue you're having on my local setup? – ash Jul 27 '15 at 19:43
  • Thank You for your concern download the SQL Data here http://youth-arena.com/portal/sql.sql and the code here: http://youth-arena.com/portal/query.txt – Hamzat Luqman Jul 27 '15 at 19:53

1 Answers1

2

Try this.

I've not included year and class_s in there as you may not get a reliable rowset (as you're GROUPing by admin_no).

I've included both ordinal and competition ranks - pick whichever one you need.

More info here: https://en.wikipedia.org/wiki/Ranking

I don't know the guidelines of who gets the higher rank when tied, but as a suggestion - you could do the number of subject a student studies to determine this (included in SQL for example purposes).

SET @prev_value = NULL;
SET @rank_count = 0;
SET @rank_increasing = 0;
SELECT @rank_increasing := @rank_increasing + 1 AS ordinal_rank
     , CASE
       WHEN @prev_value = a.total_score
          THEN @rank_count
       WHEN @prev_value := a.total_score
          THEN @rank_count := @rank_increasing 
        END AS competition_rank
     , a.*
  FROM ( SELECT admin_no
              , SUM(exam) + SUM(ca) AS total_score
              , SUM(exam) AS sum_exam
              , SUM(ca) AS sum_ca
              , COUNT(DISTINCT subject) AS subject_count
           FROM subjects_1
          GROUP BY admin_no
          ORDER BY total_score DESC
       ) a

Screenshot snippet

enter image description here

ash
  • 1,224
  • 3
  • 26
  • 46
  • infact thank you boss! you have indeed solved the problem beyond my expectations.Once again a big thanks to you billions time. cheers – Hamzat Luqman Jul 27 '15 at 20:50
  • Good stuff. Glad it's sorted – ash Jul 27 '15 at 20:52
  • but one more problem sir, I wish to select the rank of a particular member of the class i. e 10/00170 pls how would I do that, I have tried this but with error: .................... FROM ( SELECT admin_no , SUM(exam) + SUM(ca) AS total_score , SUM(exam) AS sum_exam , SUM(ca) AS sum_ca , COUNT(DISTINCT subject) AS subject_count FROM subjects_1 WHERE `class_s`='Grade 2' and `year`='2014/2015' GROUP BY admin_no ORDER BY total_score DESC ) a WHERE `admin_no`='10/00170' LIMIT 1 – Hamzat Luqman Jul 27 '15 at 21:14
  • How often do the results update? If it's once per year, perhaps you could store the result set in a 'ranks' table, with the rank, score and year. It'd save you having to figure out the rank each time. – ash Jul 27 '15 at 21:17
  • but i got a wrong rank,it ranked the student with 1 as his rank instead of 2 – Hamzat Luqman Jul 27 '15 at 21:22
  • Your SQL will fail as it needs the entire dataset to determine a rank. I recommend creating a 'ranks' table with the result set and year. That means you can query the 'ranks' table quickly, rather than having MySQL figure it out each time you want to determine a student rank for a given year. Add a unique constraints on admin_no and year (to prevent duplicates) and have a look a look at this: http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html – ash Jul 28 '15 at 07:24