我有以下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
依旧......
有没有办法用单个查询执行此操作?
答案 0 :(得分:1)
您可以使用GROUP BY
和MAX()
查找每个级别的最高分,然后使用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