使用mysql列出每个级别的高分

时间:2012-12-01 21:31:01

标签: mysql

我有以下2个数据库结构:

水平

CREATE TABLE IF NOT EXISTS `levels` (
  `lid` int(6) NOT NULL auto_increment,
  `name` varchar(25) NOT NULL,
  `levelcode` mediumtext character set utf8 collate utf8_unicode_ci NOT NULL,
  PRIMARY KEY  (`lid`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

高分

CREATE TABLE IF NOT EXISTS `highscores` (
  `lid` int(11) NOT NULL,
  `userid` int(6) NOT NULL,
  `score` int(8) NOT NULL,
  PRIMARY KEY  (`lid`,`userid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

我想要做的是获取所有级别的列表,以及特定用户是否具有高分,最高分或根本没有分数。对于此示例,我们使用userid'2'

这是我希望实现的结果示例表:(抱歉不知道如何制作表格)

Level ID,  Level Name,        ScoreStatus
1,         firstlevel,        noscore
2,         secondlevelname,   best score
3,         third level name,  has score

依旧......

有没有办法用单个查询执行此操作?

2 个答案:

答案 0 :(得分:1)

您可以使用GROUP BYMAX()查找每个级别的最高分,然后使用LEFT OUTER JOIN选择最高分或NULL

SELECT s.lid, lvl.name, MAX(s.score)
    FROM levels AS lvl
    LEFT OUTER JOIN highscores AS s ON lvl.lid = s.lid
    GROUP BY s.lid;

如果您想在userid 2之前对其进行限制,请在WHERE userid=2之前添加GROUP BY

  好吧,所以MAX(s.score)让我获得该等级的最高分,怎么样   我去获得用户2得分来比较他的分数,看看它是否   最好的?

啊,对......好吧,我现在不在任何MySQL的前面,并且不能完全记住细节,而不用测试就可以写出来......最简单的方法是,你会期望使用highscores时从MAX()表中选择的分数将选择整行,因此userid将与分数配对,您可以检查它是否等于2。

但是我觉得你必须在内部对该表进行排序(按分数),以便GROUP BY子句将userid放在第一行中得分最高,从而选择特定的用户。这对我来说有点笨拙。

所以你可以做的就是保留原始查询并将整个事物连接回用户表。然后测试用户的分数是否等于高分。像这样:

SELECT a.lid, a.name, IF( highscore IS NULL,
                          'no score',
                          IF( highscore = score,
                              'best score',
                              'has score' ) )
  FROM
    (SELECT s.lid, lvl.name, MAX(s.score) AS highscore
        FROM levels AS lvl
        LEFT OUTER JOIN highscores AS s ON lvl.lid = s.lid
        GROUP BY s.lid) AS a
  JOIN
    highscores s ON s.lid = a.lid
  WHERE userid = 2
  ORDER BY lid;

如果这在语法上不正确,请道歉。它应该接近你所追求的目标。

答案 1 :(得分:1)

你可以通过直接使用HighScores表来获取ALL的MAX和特定用户的MAX ...然后,加入用户表并确定要通过左边显示的消息 - 加入。因此,最内部的预先查询对每个“LID”执行所有用户的最高分,而另一个用于该用户的实际分数。

select
      L.lid,
      L.Name,
      L.LevelCode,
      if( PreQuery.HighScore is null, 'No Score', 'Score' ) as HasAScore,
      coalesce( PreQuery.HighScore, 0 ) as HighScore,
      if( PreQuery.UserHS > 0, 'User Has Score', 'No User Score' ) as UserHasAScore,
      coalesce( PreQuery.UserHS, 0 ) as UserHighScore,
      if( PreQuery.UserHS > 0 AND PreQuery.UserHS = PreQuery.HighScore, 
             'Use HAS The High Score', 'not the high score' ) as DoesUserHaveHighScore
   from
      Levels L
         LEFT JOIN ( select
                           HS.LID,
                           MAX( HS.Score ) as HighScore,
                           MAX( IF( HS.UserID = UserIDYouAreCheckingFor, HS.Score, 0 )) as UserHS
                        from
                           HighScores HS
                        group by
                           HS.LID ) PreQuery
            ON L.lid = PreQuery.LID