如何从mysql中的得分表中获取每场比赛的3个第一名?
Posted
技术标签:
【中文标题】如何从mysql中的得分表中获取每场比赛的3个第一名?【英文标题】:How to fetch 3 first places of each game from the score table in mysql? 【发布时间】:2010-10-14 18:20:03 【问题描述】:我有下表:
CREATE TABLE `score` (
`score_id` int(10) unsigned NOT NULL auto_increment,
`user_id` int(10) unsigned NOT NULL,
`game_id` int(10) unsigned NOT NULL,
`thescore` bigint(20) unsigned NOT NULL,
`timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP,
PRIMARY KEY (`score_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
这是一个分数表,存储了每场比赛的 user_id 和 game_id 和分数。 每场比赛的前3名都有奖杯。 我有一个 user_id,我想检查该特定用户是否从任何游戏中获得任何奖杯。
我可以在不创建临时表的情况下以某种方式创建此查询吗?
【问题讨论】:
您可以使用子查询而不是临时表 【参考方案1】:SELECT s1.*
FROM score s1 LEFT OUTER JOIN score s2
ON (s1.game_id = s2.game_id AND s1.thescore < s2.thescore)
GROUP BY s1.score_id
HAVING COUNT(*) < 3;
此查询返回所有获胜游戏的行。虽然包括领带;如果分数是 10、16、16、16、18,则有四个获胜者:16、16、16、18。我不确定你是如何处理的。您需要一些方法来解决连接条件中的关系。
例如,如果平局是由较早的比赛获胜来解决的,那么您可以这样修改查询:
SELECT s1.*
FROM score s1 LEFT OUTER JOIN score s2
ON (s1.game_id = s2.game_id AND (s1.thescore < s2.thescore
OR s1.thescore = s2.thescore AND s1.score_id < s2.score_id))
GROUP BY s1.score_id
HAVING COUNT(*) < 3;
您也可以使用timestamp
列来解决关系,如果您可以依赖它是UNIQUE
。
然而,无论如何,mysql 倾向于为这种查询创建一个临时表。这是此查询的EXPLAIN
的输出:
+----+-------------+-------+------+---------------+------+---------+------+------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+---------------------------------+
| 1 | SIMPLE | s1 | ALL | NULL | NULL | NULL | NULL | 9 | Using temporary; Using filesort |
| 1 | SIMPLE | s2 | ALL | PRIMARY | NULL | NULL | NULL | 9 | |
+----+-------------+-------+------+---------------+------+---------+------+------+---------------------------------+
【讨论】:
是的,这看起来不错。您只需要添加“WHERE s1.user_id='blah'”,因为提问者已经有他想要的特定 user_id,而且对于大型数据集,这可能会使查询更快。【参考方案2】:一种更清晰的方法,并且经过半测试。
SELECT DISTINCT user_id FROM ( select s.user_id, s.game_id, s.thescore, (SELECT count(1) from scores where game_id = s.game_id AND thescore > s.thescore ) AS acount FROM scores s ) AS a
WHERE 帐号
【讨论】:
提问者说“我有一个 user_id,我想检查...”,所以我认为他真的想要该用户的游戏和奖杯列表。但看起来你正在向他提供 user_ids 列表。【参考方案3】:没有测试,但应该可以正常工作:
SELECT
*,
@position := @position + 1 AS position
FROM
score
JOIN (SELECT @position := 0) p
WHERE
user_id = <INSERT_USER_ID>
AND game_id = <INSERT_GAME_ID>
ORDER BY
the_score
您可以在此处检查 position 字段以查看它是否在 1 和 3 之间。
【讨论】:
这行不通,因为@position 变量仅针对结果集中的行计算,并且由于您有“WHERE user_id=...”,因此只有该用户的分数将是在您的结果集中,位置列只会告诉您用户的分数在该列表中的位置。【参考方案4】:SELECT game_id, user_id
FROM score score1
WHERE (SELECT COUNT(*) FROM score score2
WHERE score1.game_id = score2.game_id AND score2.thescore > score1.thescore) < 3
ORDER BY game_id ASC, thescore DESC;
【讨论】:
我想获得每场比赛的前 3 名。此查询将提供所有表的前 3 个位置。以上是关于如何从mysql中的得分表中获取每场比赛的3个第一名?的主要内容,如果未能解决你的问题,请参考以下文章