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

HighScores テーブルを参照するだけで、ALL の MAX と特定のユーザーの MAX の両方を取得することで実行できます。次に、user テーブルに結合し、左結合を介して表示するメッセージを修飾します。したがって、最も内側のプレクエリは、「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 に答える
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;

これを 2 で制限したい場合は、 の前にuserida を追加します。WHERE userid=2GROUP 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 に答える