【问题标题】:How to Rank in MySQL Using a WHERE clause and UNION ALL如何使用 WHERE 子句和 UNION ALL 在 MySQL 中排名
【发布时间】:2010-08-03 16:01:57
【问题描述】:

我需要一些有关 MySQL 查询的帮助。我正在尝试使用 WHERE 子句对参与者进行排名。所以,我想分别对新手、中级和经验者进行排名。例如:

Rank Name    Grade  Type
----------------------------------
1    Bob     98     Novice 
2    Jill    88     Novice 
3    Jimmy   42     Novice 
1    Mark    87     Intermediate 
2    Scott   85     Intermediate
3    Jim     77     Intermediate 
1    Jane    90     Advanced 
2    John    89     Advanced 
3    Josh    87     Advanced

我试过了:

SET @rank=0;

(SELECT @rank:=@rank+1 AS rank, name, grade, type FROM myTable WHERE type='novice' ORDER BY grade DESC)
UNION ALL
(SELECT @rank:=@rank+1 AS rank, name, grade, type FROM myTable WHERE type='intermediate' ORDER BY grade DESC)
UNION ALL
(SELECT @rank:=@rank+1 AS rank, name, grade, type FROM myTable WHERE type='experienced' ORDER BY grade DESC)

我想我需要以某种方式重新设置排名。也许我还有其他问题?

【问题讨论】:

    标签: mysql select ranking


    【解决方案1】:

    用途:

    SELECT t.name,
           t.grade,
           t.type,
           (SELECT COUNT(*)
              FROM YOUR_TABLE x
             WHERE x.type = t.type
               AND x.grade >= t.grade) AS rank
     FROM YOUR_TABLE t
    

    要处理两个成绩列,请使用:

    SELECT t.name,
           t.grade1,
           t.grade2,
           t.type,
           (SELECT COUNT(*)
              FROM YOUR_TABLE x
             WHERE x.type = t.type
               AND (x.grade1 + x.grade2) >= (t.grade1 + t.grade2)) AS rank
     FROM YOUR_TABLE t
    

    如何将新手和中级放在一起,将高级分开?

    用途:

    SELECT y.*,
           (SELECT COUNT(*)
              FROM (SELECT *, 
                           CASE t.type
                             WHEN 'Advanced' THEN t.type
                             ELSE 'Non-Advanced'
                           END AS group_type
                      FROM YOUR_TABLE) x
             WHERE x.group_type = y.group_type
               AND (x.grade1 + x.grade2) >= (y.grade1 + y.grade2)) AS rank
      FROM (SELECT t.name,
                   t.grade1,
                   t.grade2,
                   t.type,
                   CASE t.type
                     WHEN 'Advanced' THEN t.type
                     ELSE 'Non-Advanced'
                   END AS group_type
              FROM YOUR_TABLE t) y
    

    【讨论】:

    • 不能正确处理关系。也许你想要 COUNT(*) + 1 条件为 x.grade > t.grade。
    • @Justin K:在这种情况下,两个关系仍然会得到相同的值。假设 OP 感兴趣并解释了应该如何处理它们,最好执行一个额外的子查询来处理关系。这就是没有分析/排名/窗口功能的生活:/
    • 我假设我们使用可能的最高等级作为平局。因此,如果两个人的最高分相同,他们都应该获得排名 1。(我同意下一个人获得 2 或 3 是主观的。)
    • 嗨 OMGPonies,你是 MySQL OMGStallion。你总是帮助我。当我尝试上述方法时,我收到一条错误消息。什么是表 x?我需要用类型制作一个单独的表吗?它是一个“虚拟桌子”吗?我得到:#1064 - 您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以在第 5 行的“TABLE x WHERE x.type = t.type AND x.grade >= t.grade) AS run”附近使用正确的语法谢谢!
    • @Laxmidi:和t 是同一张表。我将更新答案以使其更加明显。我很庆幸自己是一匹种马,而不是一匹骟马;)
    【解决方案2】:

    您可以使用更复杂的ORDER BY 子句一次性完成。

    SELECT @rank:=@rank+1 AS rank, name, grade, type 
    FROM myTable 
    ORDER BY 
        case type when 'novice'       then 1
                  when 'intermediate' then 2 
                  when 'experienced'  then 3 end,
        grade DESC
    ;
    

    为了让它变得更好,您可以使用Type 表来存储排序顺序,然后添加一个连接,然后简单地按 type.sort_order 然后按等级排序,例如。

    SELECT @rank:=@rank+1 AS rank, name, grade, type 
    FROM myTable 
    JOIN Types ON myTable.type = Types.type 
    ORDER BY Types.sort_order, grade DESC;
    

    【讨论】:

    • 您好,谢谢您的帖子!我尝试了您列出的第一个选项。不幸的是,我得到了 1-9 的排名(而不是每种类型的 1-3)。它返回:等级名称等级类型 1 Jane 90 高级 2 John 89 高级 3 Josh 87 高级 4 Bob 98 新手 5 Jill 88 新手 6 Jimmy 42 新手 7 Mark 87 中级 8 Scott 85 中级 9 Jim 77 中级我正在尝试为每种类型单独排名。有什么建议么?谢谢!
    • 嗨,对不起,我有 mySQL 返回的一个小表格,但是当我把它放在评论中时它丢失了格式。
    猜你喜欢
    • 1970-01-01
    • 2021-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多