1

我有下表:

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,我想检查该特定用户是否从任何游戏中获得任何奖杯。

我可以在不创建临时表的情况下以某种方式创建此查询吗?

4

4 回答 4

1
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;
于 2009-03-21T19:24:39.797 回答
1

一种更清晰的方法,并且经过半测试。

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

其中帐户 < 3

于 2009-03-21T19:39:00.557 回答
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 |                                 | 
+----+-------------+-------+------+---------------+------+---------+------+------+---------------------------------+
于 2009-03-21T20:46:27.057 回答
0

没有测试它,但应该可以正常工作:

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

在那里您可以检查位置字段以查看它是否在 1 和 3 之间。

于 2009-03-21T19:32:29.107 回答