如何使用 MySQL 从复杂查询中获取条目的位置?
How to get an entry's position from a complex query using MySQL?
我想知道玩家在排行榜上的位置(排名)。我没有排行榜 table,它是从 users
table 和查询生成的。这就是我获取条目的方式:
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
是一个单独的 table ,我在其中保存玩家玩过的游戏结果:
+----+------------+-----------+-----------------+---------+
| 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): Unknown column 'u.xp' in 'where clause'
据我所知,MySQL 只允许 1 级深度嵌套或子查询,但在我的示例中我是 3 级深度。但是如何从子查询引用到外部查询呢?
这是获得排行榜的正确方法吗?我应该创建一个单独的 table 并定期更新它吗? 我很害怕性能受到影响。
我正在使用 MySQL 8.0 版本。
使用 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;
| userId | xp | nickname | wonGames | lostGames | rnk |
| ------ | --- | -------- | -------- | --------- | --- |
| 1 | 34 | nick1 | 4 | 5 | 1 |
| 3 | 29 | nick3 | 7 | 8 | 2 |
| 2 | 29 | nick2 | 4 | 5 | 2 |
我想知道玩家在排行榜上的位置(排名)。我没有排行榜 table,它是从 users
table 和查询生成的。这就是我获取条目的方式:
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
是一个单独的 table ,我在其中保存玩家玩过的游戏结果:
+----+------------+-----------+-----------------+---------+
| 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): Unknown column 'u.xp' in 'where clause'
据我所知,MySQL 只允许 1 级深度嵌套或子查询,但在我的示例中我是 3 级深度。但是如何从子查询引用到外部查询呢?
这是获得排行榜的正确方法吗?我应该创建一个单独的 table 并定期更新它吗? 我很害怕性能受到影响。
我正在使用 MySQL 8.0 版本。
使用 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;
| userId | xp | nickname | wonGames | lostGames | rnk |
| ------ | --- | -------- | -------- | --------- | --- |
| 1 | 34 | nick1 | 4 | 5 | 1 |
| 3 | 29 | nick3 | 7 | 8 | 2 |
| 2 | 29 | nick2 | 4 | 5 | 2 |