0

我有以下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

等等..

有没有办法用一个查询来做到这一点?

4

2 回答 2

1

您可以使用GROUP BYMAX()查找每个级别的最高分,然后使用 aLEFT 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;

如果您想将此限制为userid2 WHERE userid=2,请在GROUP BY.

好的,所以 MAX( s.score ) 让我获得了该级别的最佳分数,我将如何获得 userids 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;

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

于 2012-12-01T21:39:42.137 回答
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 
于 2012-12-02T01:30:49.843 回答