【问题标题】:MySQL query to update rankingMySQL查询更新排名
【发布时间】:2017-05-29 20:40:52
【问题描述】:

我有一个 mysql 表,其中包含用户 ID、评级和排名作为字段。该表很大(> 10K 行)。我正在尝试根据评级更新单个查询中每一行的排名列(评级越高,排名越低)。如果 2 个或更多用户具有相同的评分,他们具有相同的排名,但下一个排名将跳过那么多用户(如果 2 个用户的排名为 5,那么下一个用户将是排名 7)。

我正在尝试通过以下查询来实现这一点,但不知道我哪里出错了。

UPDATE userprofile
            JOIN (SELECT p.userid,
                         IF(@last_rating<> p.rating,
                            @cur_rank := @cur_rank + @next_rank,
                            @cur_rank)  AS ranking,
                         IF(@last_rating= p.rating,
                            @next_rank := @next_rank + 1,
                            @next_rank := 1),
                         @last_rating:= p.rating
                    FROM userprofile p
                    JOIN (SELECT @cur_rank := 0, @last_rating:= -1, @next_rank := 1) r
                   ORDER BY  p.rating DESC
                  ) ranks ON (ranks.userid = userprofile.userid)
        SET userprofile.ranking = ranks.ranking

这是查询前的表格示例

+--------+--------+-----+------+------------+--------+--------------+---------+---------------+
| userid | played | won | lost |   streak   | rating | ratingchange | ranking | currentgameid |
+--------+--------+-----+------+------------+--------+--------------+---------+---------------+
|      1 |      1 |   0 |    0 | A          |      0 |            0 |       0 |             6 |
|      2 |      1 |   1 |    0 | W          |     50 |           50 |       0 |             2 |
|      7 |     13 |   4 |    5 | AWLLLWWLLW |    108 |           48 |       0 |             0 |
|      8 |      6 |   6 |    0 | WWWWWW     |    198 |           48 |       0 |             0 |
|      9 |      1 |   0 |    0 | A          |      0 |            0 |       0 |             0 |
|     10 |      1 |   1 |    0 | W          |     50 |           50 |       0 |             0 |
|     11 |      7 |   5 |    2 | WWWLWWL    |    142 |          -48 |       0 |             0 |
|     12 |      7 |   1 |    6 | LLLWLLL    |      0 |            0 |       0 |            26 |
|     13 |      5 |   3 |    1 | LWWAW      |     71 |           71 |       0 |             0 |
|     14 |      1 |   1 |    0 | W          |     71 |           71 |       0 |             0 |
|     15 |      0 |   0 |    0 |            |      0 |            0 |       0 |            26 |
+--------+--------+-----+------+------------+--------+--------------+---------+---------------+

查询之后

+--------+--------+-----+------+------------+--------+--------------+---------+---------------+
| userid | played | won | lost |   streak   | rating | ratingchange | ranking | currentgameid |
+--------+--------+-----+------+------------+--------+--------------+---------+---------------+
|      1 |      1 |   0 |    0 | A          |      0 |            0 |       1 |             6 |
|      2 |      1 |   1 |    0 | W          |     50 |           50 |       2 |             2 |
|      7 |     13 |   4 |    5 | AWLLLWWLLW |    108 |           48 |       3 |             0 |
|      8 |      6 |   6 |    0 | WWWWWW     |    198 |           48 |       4 |             0 |
|      9 |      1 |   0 |    0 | A          |      0 |            0 |       5 |             0 |
|     10 |      1 |   1 |    0 | W          |     50 |           50 |       6 |             0 |
|     11 |      7 |   5 |    2 | WWWLWWL    |    142 |          -48 |       7 |             0 |
|     12 |      7 |   1 |    6 | LLLWLLL    |      0 |            0 |       8 |            26 |
|     13 |      5 |   3 |    1 | LWWAW      |     71 |           71 |       9 |             0 |
|     14 |      1 |   1 |    0 | W          |     71 |           71 |       9 |             0 |
|     15 |      0 |   0 |    0 |            |      0 |            0 |      11 |            26 |
+--------+--------+-----+------+------------+--------+--------------+---------+---------------+

如果我使用如下 select 语句,它会在 ranks.ranking 列中给出预期的结果,但 SET 语句没有按预期工作。

SELECT userprofile.userid, userprofile.rating, ranks.userid, ranks.ranking FROM userprofile
            JOIN (SELECT p.userid,
                         IF(@last_rating<> p.rating,
                            @cur_rank := @cur_rank + @next_rank,
                            @cur_rank)  AS ranking,
                         IF(@last_rating= p.rating,
                            @next_rank := @next_rank + 1,
                            @next_rank := 1),
                         @last_rating:= p.rating
                    FROM userprofile p
                    JOIN (SELECT @cur_rank := 0, @last_rating:= -1, @next_rank := 1) r
                   ORDER BY  p.rating DESC
                  ) ranks ON (ranks.userid = userprofile.userid)

选择查询的结果

+--------+--------+--------+---------+
| userid | rating | userid | ranking |
+--------+--------+--------+---------+
|      8 |    198 |      8 |       1 |
|     11 |    142 |     11 |       2 |
|      7 |    108 |      7 |       3 |
|     13 |     71 |     13 |       4 |
|     14 |     71 |     14 |       4 |
|      2 |     50 |      2 |       6 |
|     10 |     50 |     10 |       6 |
|      1 |      0 |      1 |       8 |
|      9 |      0 |      9 |       8 |
|     12 |      0 |     12 |       8 |
|     15 |      0 |     15 |       8 |
+--------+--------+--------+---------+

【问题讨论】:

  • 请准确描述出了什么问题,不要让我们也弄清楚!
  • 将表格和数据发布为文本READ THIS
  • 在这里很难将我的表格数据复制为文本。您能推荐任何可以将由字符分隔的文本转换为可以粘贴到此处的文本的软件吗?
  • 你能复制/粘贴到excel吗? Excel 到该网站的工作非常容易。

标签: mysql rank


【解决方案1】:

您可以创建一个临时表,然后执行更新吗?

SQL DEMO

CREATE TABLE test as 
SELECT userprofile.*, ranks.ranking  as newRank
FROM userprofile
JOIN (SELECT p.userid,
             IF(@last_rating<> p.rating,
                @cur_rank := @cur_rank + @next_rank,
                @cur_rank)  AS ranking,
             IF(@last_rating= p.rating,
                @next_rank := @next_rank + 1,
                @next_rank := 1),
             @last_rating:= p.rating
      FROM userprofile p
      JOIN (SELECT @cur_rank := 0, @last_rating:= -1, @next_rank := 1) r
      ORDER BY  p.rating DESC
    ) ranks 
ON (ranks.userid = userprofile.userid);

更新

UPDATE userprofile
JOIN test
  ON userprofile.`userid`  = test.`userid`
SET userprofile.ranking = test.newRank;

【讨论】:

  • 我已经修改了答案中给出的SQL。为什么 UPDATE 和创建排名不能在同一个查询中工作?
  • manualHowever, the order of evaluation for expressions involving user variables is undefined.中有一行我正在尝试看看是否有办法强制订购。但与此同时,这是一种简单的方法,因此您可以继续解决您的问题。
  • 供您参考,this 是我的做法。但仍然是同样的问题。看起来尝试使用原始表顺序。这就是为什么10 是数字`,如果数据的顺序正确,则更新正常。
【解决方案2】:

这是最终对我有用的查询。 选择胡安的答案作为接受的答案,因为它是建议这样做的答案。

DROP TABLE IF EXISTS t1;

CREATE TABLE t1 AS
SELECT userprofile.userid, ranks.ranking FROM userprofile
            JOIN (SELECT p.userid,
                         IF(@last_rating<> p.rating,
                            @cur_rank := @cur_rank + @next_rank,
                            @cur_rank)  AS ranking,
                         IF(@last_rating= p.rating,
                            @next_rank := @next_rank + 1,
                            @next_rank := 1),
                         @last_rating:= p.rating
                    FROM userprofile p
                    JOIN (SELECT @cur_rank := 0, @last_rating:= -1, @next_rank := 1) r
                   ORDER BY  p.rating DESC
                  ) ranks ON (ranks.userid = userprofile.userid);

UPDATE userprofile JOIN t1 ON userprofile.userid = t1.userid
SET userprofile.ranking = t1.ranking;

DROP TABLE t1;

【讨论】:

  • 以防万一,您应该以DROP TABLE IF EXISTS t1;开头
  • 注意,非常感谢您的帮助。在答案中更新
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-02-18
  • 2020-05-26
  • 2011-12-12
  • 1970-01-01
  • 1970-01-01
  • 2014-07-24
  • 2012-12-31
相关资源
最近更新 更多