使用Php和Mysql根据学生的总分进行排名,并给出排名。如果存在并列,则不要连续排名。

7

我有一个非常简单的MySQL表格,用于保存每个学生的科目、考试和CA分数以及他们的管理编号。它看起来像这样:

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

我使用以下mysql查询来对所有科目的考试分数和CA进行求和,然后将每个学生的所有分数作为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 

查询的输出:

 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**

问题:输出结果不错,但在最后三个排名中有问题。即总分12出现两次,分别为14/00346和15/00371,它们被赋予了相同的排名,这很好,但是紧随12之后的是7,而它的排名是15,而不是17。请帮助我,如果总分相同,则不要让排名连续。
以下是我的mysql数据副本 http://youth-arena.com/portal/sql.sql 以下是php查询代码。

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


如果我理解正确的话,您想要增加排名(即使并列)? 如果是这样,您应该通过删除“IF”语句并仅调用“@auto:= @auto + 1”来实现。唯一的问题是,如何确定谁获得14和15名?MySQL会尝试为您解决此问题,但结果可能是间歇性的。 - ash
@jeroen 非常感谢,我已经移除了if语句并使用了这个代码: 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 <br> 因此,正如您所提到的,这将带我进入另一个问题级别,即为相同的总分数提供不同的排名。请帮我提供完整的可行代码。谢谢! - Hamzat Luqman
双面胶带,谢谢先生。请问我还在等待如何使用这个脚本正确地获取排名。 - Hamzat Luqman
抱歉Hsmzat,我现在不在家。很高兴看到你已经(几乎)解决了这个问题 - 当总分相同时,还有什么其他决定因素可以确定谁获得更高的排名(如果有的话)? - ash
好的,我成功地建立了一个MySQL设置,因此在我不在的时候,你能否以一种更多(去敏感化)数据的方式编辑你的问题,并在问题中提供,以便我可以在我的本地设置中复制你正在遇到的排名问题? - ash
显示剩余4条评论
1个回答

2

试一下这个。

我没有包括yearclass_s,因为你可能得不到可靠的行集(因为你是按admin_no进行GROUP的)。

我包括了ordinalcompetition排名 - 选择你需要的任何一个。

更多信息请参见:https://en.wikipedia.org/wiki/Ranking

我不知道并列时谁获得更高的排名的准则,但作为建议 - 你可以根据学生学习的科目数量来确定这一点(在SQL中包含示例目的)。

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

截图片段

enter image description here


实际上,谢谢老板!您确实超出了我的期望解决了这个问题。再次感谢您亿万次。干杯! - Hamzat Luqman
好东西。很高兴它被解决了。 - ash
但是还有一个问题,我想选择班级中特定成员的排名,例如10/00170,请问我该如何做?我已经尝试了以下代码,但出现了错误: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
结果更新频率是多少?如果是每年一次,也许你可以将结果集存储在一个“排名”表中,包括排名、得分和年份。这样就不用每次都计算排名了。 - ash
但是我得到了一个错误的排名,它把学生的排名从2变成了1。 - Hamzat Luqman
你的SQL将会失败,因为它需要整个数据集来确定排名。我建议创建一个包含结果集和年份的“ranks”表。这意味着你可以快速查询“ranks”表,而不是每次想要确定给定年份的学生排名时都让MySQL去计算。在admin_no和year上添加唯一约束(以防止重复),并查看此链接:http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html - ash

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接