我有一张表记录用户在游戏中的得分(用户可以提交5,10,20,他想要的分数)。 我需要显示一个游戏的20个最高分,但是每个用户。 (因为用户可能已根据其他用户的分数提交了例如4个分数,这是最高分) 我写的查询是:
SELECT DISTINCT
`table_highscores`.`userkey`,
max(`table_highscores`.`score`),
`table_users`.`username`,
`table_highscores`.`dateachieved`
FROM
`table_highscores`, `table_users`
WHERE
`table_highscores`.`userkey` = `table_users`.`userkey`
AND
`table_highscores`.`gamekey` = $gamekey
GROUP BY
`userkey`
ORDER BY
max(`table_highscores`.`score`) DESC,
LIMIT 0, 20;
输出结果没问题,但是有问题。当我计算天数的差异(今天 - dateachieved
的这个)时,结果是错误的。 (例如,而不是说“分数是在22天前提交的,它说的是43天前)所以,我必须对每个分数进行第二次查询,以便找到真实的日期(意味着+20个查询)。有没有更短的方式找到正确的日期?
感谢。
答案 0 :(得分:3)
有问题。当我计算天数的差异(今天 - 这个日期的差异)时,结果是错误的。
有两个问题
dateachieved
不太可能是与高分相关的值dateachieved
值之间的天数。 使用:
SELECT u.username,
hs.userkey,
hs.score,
DATEDIFF(NOW(), hs.dateachieved)
FROM TABLE_HIGHSCORES hs
JOIN TABLE_USERNAME u ON u.userkey = hs.userkey
JOIN (SELECT ths.userkey,
ths.gamekey,
ths.max_score,
MAX(ths.date_achieved) 'max_date'
FROM TABLE_HIGHSCORES ths
JOIN (SELECT t.userkey,
t.gamekey,
MAX(t.score) 'max_score'
FROM TABLE_HIGHSCORES t
GROUP BY t.userkey, t.gamekey) ms ON ms.userkey = ths.userkey
AND ms.gamekey = ths.gamekey
AND ms.max_score = ths.score
) x ON x.userkey = hs.userkey
AND x.gamekey = hs.gamekey
AND x.max_score = hs.score
AND x.max_date = hs.dateachieved
WHERE hs.gamekey = $gamekey
ORDER BY hs.score DESC
LIMIT 20
我还将您的查询更改为使用ANSI-89 JOIN语法,来自ANSI-89语法。它具有相同的性能,但它更容易阅读,Oracle / SQL Server / Postgres /等支持语法,并提供一致的LEFT JOIN支持。
另一件事 - 当表和/或列名是MySQL关键字时,你只需要使用反引号。
答案 1 :(得分:2)
在您的查询中,您应该使用显式JOIN,而不需要DISTINCT关键字。
此查询应解决您的问题。我在这里假设用户可以在不同的日期多次提交相同的高分,如果发生这种情况,那么你想要最早的日期:
SELECT T1.userkey, T1.score, username, dateachieved FROM (
(SELECT userkey, max(score) AS score
FROM table_highscores
WHERE gamekey = $gamekey
GROUP BY userkey) AS T1
JOIN
(SELECT userkey, score, min(dateachieved) as dateachieved
FROM table_highscores
WHERE gamekey = $gamekey
GROUP BY userkey, score) AS T2
ON T1.userkey = T2.userkey AND T1.score = T2.score
) JOIN table_users ON T1.userkey = table_users.userkey
LIMIT 20
答案 2 :(得分:1)
你没有说出你用什么语言来计算差异但是我猜它是PHP因为你在那里使用$gamekey
(应该正确转义,顺便说一下)。
如果您的datepaieved字段是DATETIME格式,您可以像这样计算差异:
$diff = round((time() - strtotime($row['dateachieved'])) / 86400);
答案 3 :(得分:0)
我认为你需要更好地澄清你的问题。您能否提供一些数据和预期产出,然后我应该能够为您提供进一步的帮助?