【问题标题】:How do I Handle Ties When Ranking Results in MySQL?在 MySQL 中对结果进行排名时如何处理平局?
【发布时间】:2011-01-29 06:49:57
【问题描述】:

在 mysql 查询中对结果进行排名时如何处理平局?我在这个例子中简化了表名和列,但它应该能说明我的问题:

SET @rank=0;

   SELECT student_names.students, 
          @rank := @rank +1 AS rank, 
          scores.grades
     FROM student_names  
LEFT JOIN scores ON student_names.students = scores.students
 ORDER BY scores.grades DESC

所以想象一下上面的查询产生:

Students  Rank  Grades
=======================
Al         1     90
Amy        2     90
George     3     78
Bob        4     73
Mary       5     NULL
William    6     NULL

虽然 Al 和 Amy 的成绩相同,但其中一个的排名高于另一个。艾米被骗了。我怎样才能使 Amy 和 Al 具有相同的排名,使他们都有 1 的排名。另外,William 和 Mary 没有参加测试。他们打包上课,在男孩的房间里抽烟。他们应该并列最后一名。

正确的排名应该是:

Students  Rank  Grades
========================
Al         1     90
Amy        1     90
George     2     78
Bob        3     73
Mary       4     NULL
William    4     NULL

如果有人有任何建议,请告诉我。

【问题讨论】:

    标签: mysql sql rank window-functions


    【解决方案1】:

    编辑:这是 MySQL 4.1+ 支持的

    用途:

       SELECT st.name,
              sc.grades,
              CASE 
                WHEN @grade = COALESCE(sc.grades, 0) THEN @rownum 
                ELSE @rownum := @rownum + 1 
              END AS rank,
              @grade := COALESCE(sc.grades, 0)
         FROM STUDENTS st
    LEFT JOIN SCORES sc ON sc.student_id = st.id
         JOIN (SELECT @rownum := 0, @grade := NULL) r
     ORDER BY sc.grades DESC
    

    您可以使用交叉联接(在 MySQL 中,是不带任何条件的 INNER JOIN)来声明和使用变量,而无需使用单独的 SET 语句。

    您需要 COALESCE 来正确处理 NULL。

    【讨论】:

    • 嗨 OMG 小马们,你们是 MySQL 终结者!太棒了,非常感谢您的帮助。我永远也想不通。 (我的 SQL 知识很基础,所以我必须研究你的答案才能更好地理解它)。另外,我喜欢你的网名。再次,谢谢!!! -Laxmidi
    • “您可以使用交叉连接(在 MySQL 中,一个没有任何条件的 INNER JOIN)来声明和使用变量,而无需使用单独的 SET 语句。”该死的,我不知道你能做到这一点。 +1
    • OMG Ponies - 我试用了您的解决方案,效果很好。但我必须承认我仍然不完全确定它是如何工作的。您能否添加更多关于如何让相同年级的学生获得相同分数的详细信息?或者,如果其他地方有描述此技术的链接。谢谢!
    • @Brian Armstrong:当等级变量等于当前行或零时,CASE 语句将重复 rownum 值。否则,排名值将增加并显示为该行。 SELECT 子句中的最后一列将等级值设置为用于与下一个等级值进行比较的变量。 ORDER BY 确保排名最高的成绩将具有最低的数字。
    【解决方案2】:

    听起来像是一个中间件规则,最好用位于数据库和客户端之间的代码来表达。

    如果这不可能,我建议在 MySQL 中使用存储过程来运行您编写的查询,然后使用游标和数组修改结果。

    【讨论】:

    • 嗨,达菲莫,谢谢您的评论。我很感激帮助。 -Laxmidi
    • OMG Ponies 是这个人。多么棒的答案。
    猜你喜欢
    • 1970-01-01
    • 2021-06-29
    • 1970-01-01
    • 1970-01-01
    • 2021-11-04
    • 2012-05-22
    • 2017-05-10
    • 2021-04-06
    • 2018-07-25
    相关资源
    最近更新 更多