如何从使用MySQL一个复杂的查询入口的位置?

问题描述 投票:2回答:1

我想知道从排行榜玩家的位置(排名)。我并没有排行榜表,它正在从users表和查询生成。这是我得到的条目:

SELECT
   u.id as userId,
   u.xp as xp,
   u.nickname as nickname,
   SUM(opr.games_won) as wonGames,
   SUM(opr.games_lost) as lostGames 
FROM
   users u 
   INNER JOIN
      opponent_player_result opr ON u.id = opr.user_id 
WHERE
   u.last_login >= 1548374400000 
   AND u.xp > 0 
   AND u.zone_id = 1 
GROUP BY
   u.id 
ORDER BY
   u.xp DESC,
   wonGames DESC,
   lostGames ASC
LIMIT 0, 50;

xp栏是用于存储玩家的经验值。每场比赛后,在更新播放此列。

opponent_player_result是分隔的表,我保持玩家的玩的游戏的结果:

+----+------------+-----------+-----------------+---------+
| id | games_lost | games_won | opponent_player | user_id |
+----+------------+-----------+-----------------+---------+
|  1 |          3 |         0 |               0 |       1 |
|  2 |          2 |         1 |               1 |       1 |
|  3 |          0 |         3 |               2 |       1 |
|  4 |          4 |         2 |               0 |       2 |
|  5 |          0 |         1 |               1 |       2 |
|  6 |          1 |         1 |               2 |       2 |
|  7 |          2 |         3 |               0 |       3 |
|  8 |          3 |         0 |               1 |       3 |
|  9 |          3 |         4 |               2 |       3 |
+----+------------+-----------+-----------------+---------+

正如你可能已经注意到,每个玩家都具有3个对手选手的结果(因为只有3个机器人,玩家可以玩)。

上面的查询会给我以下结果:

+--------+----+----------+----------+-----------+
| userId | xp | nickname | wonGames | lostGames |
+--------+----+----------+----------+-----------+
|      1 | 34 | nick1    |        4 |         5 |
|      3 | 29 | nick3    |        7 |         8 |
|      2 | 29 | nick2    |        4 |         5 |
+--------+----+----------+----------+-----------+

我不使用MySQL RANK()功能,无论我不递增变量玩家位置关联(也许这是我应该做的)。

如何从上面的排行榜结果的单一玩家的位置?

例如,#id 3用户将有秩2

这是我的工作,以找到在排行榜中的玩家的位置查询:

SELECT u.id AS userId,
       u.xp AS xp,
       1 +
  (SELECT COUNT(*)
   FROM
     (SELECT SUM(opr.games_won) AS wonGames,
             SUM(opr.games_lost) AS lostGames
      FROM users AS p
      INNER JOIN opponent_player_result AS opr ON p.id = opr.user_id
      WHERE p.last_login >= 1548374400000
        AND p.xp > 0
        AND p.xp > u.xp
        AND p.zone_id = 1
      GROUP BY p.id
      ORDER BY p.xp DESC, wonGames DESC, lostGames ASC) AS counter) AS ranking
FROM users AS u
WHERE u.id = 1;

但我发现了以下错误:

ERROR 1054(42S22):未知列 'u.xp' 在 'where子句'

据我所知,MySQL允许只有1级深嵌套子查询或,但在我的例子,我3级深。但是,如何从子查询,然后参照外部查询?

这是获得领先的正确方法?我应该创建一个分离的表,并定期更新呢?我很害怕性能损失。

我使用MySQL 8.0版本。

mysql sql rank
1个回答
2
投票

这是简单的使用MySQL 8.0的排名函数。例如,DENSE_RANK计算一个分区中的每一行的排名(并列记录被分配了相同级别)。

SELECT
   u.id as userId,
   u.xp as xp,
   u.nickname as nickname,
   SUM(opr.games_won) as wonGames,
   SUM(opr.games_lost) as lostGames,
   DENSE_RANK() OVER(ORDER BY u.xp DESC) rnk
FROM
   users u 
   INNER JOIN
      opponent_player_result opr ON u.id = opr.user_id 
WHERE
   u.last_login >= 1548374400000 
   AND u.xp > 0 
   AND u.zone_id = 1 
GROUP BY
   u.id, u.xp, u.nickname
ORDER BY
   u.xp DESC,
   wonGames DESC,
   lostGames ASC
LIMIT 0, 50;

Demo on DB Fiddle

| userId | xp  | nickname | wonGames | lostGames | rnk |
| ------ | --- | -------- | -------- | --------- | --- |
| 1      | 34  | nick1    | 4        | 5         | 1   |
| 3      | 29  | nick3    | 7        | 8         | 2   |
| 2      | 29  | nick2    | 4        | 5         | 2   |
© www.soinside.com 2019 - 2024. All rights reserved.