这是我遇到的一个真正的菜鸟 MySQL 查询问题。
我正在编写的游戏中有一个高分表。高分DB记录姓名、等级以及获得的分数。数据库中有许多接近重复的内容。例如:
Name | Level | Score | Timestamp (key)
Bob 2 41 | 1234567.890
Bob 3 15 | 1234568.890
Bob 3 20 | 1234569.890
Joe 2 40 | 1234561.890
Bob 3 21 | 1234562.890
Bob 3 21 | 1234563.890
我想返回“达到的最高级别”高分列表,其输出类似于:
Name | Level | Score
Bob 3 21
Joe 2 40
我当前使用的 SQL 查询是:
SELECT *, MAX(level) as level
FROM highscores
GROUP BY name
ORDER BY level DESC, score DESC
LIMIT 5
但是这并不完全有效。 “分数”字段输出似乎总是从组中随机抽取,而不是获取达到的最高级别的相应分数。例如:
Name | Level | Score
Bob 3 41
Joe 2 40
鲍勃在第 3 级从未获得过 41 分!我该如何解决这个问题?
最佳答案
您需要使用子查询来提取分数。
select distinct
name,
max(level) as level,
(select max(score) from highscores h2
where h2.name = h1.name and h2.level = h1.level) as score
from highscores h1
group by name
order by level desc, score desc
干杯,
埃里克
令我烦恼的是,当我发布答案时,我没有花时间解释为什么会出现这种情况,所以这里是:
当您拉回所有内容 (*),然后拉动最大级别时,您将得到的是按顺序排列的每个记录,以及其上具有最大级别的列。请注意,您没有按分数分组(这会给您 Bob 2 41 和 Bob 3 21——我们的 friend Bob 的两条记录)。
那么,我们到底该如何解决这个问题呢?您需要执行一个子查询来额外过滤您的结果,这就是 (select max(score)...) 。现在,对于鲍勃的每一行,您将获得他的最高级别 (3) 以及他在该级别的最高分数 (21)。但是,这仍然给我们提供了 Bob 有多少行(例如,如果他有 5 行,您将得到 5 行 Bob 3 21)。为了将其限制为仅最高分,我们需要在 select 语句中使用 DISTINCT 子句以仅返回唯一的行。
更新:正确的 SQL(无法评论 le dorfier 的帖子):
SELECT h1.Name, h1.Level, MAX(h1.Score)
FROM highscores h1
LEFT OUTER JOIN highscores h2 ON h1.name = h2.name AND h1.level < h2.level
LEFT OUTER JOIN highscores h3 ON h1.name = h3.name AND h2.level = h3.level AND h1.score < h3.score
WHERE h2.Name IS NULL AND h3.Name IS NULL
GROUP BY h1.Name, h1.Level
关于MySQL 在 Group By 查询中选择错误的列值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/788095/