5

いくつかの簡単なコンピューターゲームの結果を表示し、コード内で結果を1行ずつ簡単に反復できるようにしようとしています。各ゲームに関連するすべてのデータが各レコードに含まれるようにして、すべてを1行で出力できるようにします。例:

  • チームA(スコア45)対チームB(スコア55)、ゲーム時間:5
  • チームC(スコア60)対チームD(スコア65)、ゲーム時間:4.3

したがって、ゲームの場合、互いにプレイする2つのチームがあり、ゲームの終了時にそれぞれがスコアを取得します。基本的に、ゲームごとにgames_teamsテーブルに2つの行があります。

これが私のスキーマです:

スキーマ写真

これが私のテーブルデータです:

テーブルデータ写真

結果を簡単に繰り返してページに出力できるように、私が達成しようとしている出力は次のとおりです。

希望の出力写真

私はいくつかの恐ろしいSQLと次のような多くのサブクエリでそれを達成することができました:

SELECT games.game_id, game_name, game_duration, 
(SELECT team_id FROM games_teams WHERE games.game_id = games_teams.game_id LIMIT 0, 1) AS team_id_a,
(SELECT team_id FROM games_teams WHERE games.game_id = games_teams.game_id LIMIT 1, 1) AS team_id_b,
(SELECT teams.team_name FROM games_teams INNER JOIN teams ON games_teams.team_id = teams.team_id WHERE games.game_id = game_id LIMIT 0, 1) AS team_name_a,
(SELECT teams.team_name FROM games_teams INNER JOIN teams ON games_teams.team_id = teams.team_id WHERE games.game_id = game_id LIMIT 1, 1) AS team_name_b,
(SELECT team_score FROM games_teams WHERE games.game_id = games_teams.game_id LIMIT 0, 1) AS team_score_a,
(SELECT team_score FROM games_teams WHERE games.game_id = games_teams.game_id LIMIT 1, 1) AS team_score_b
FROM games

その方法の問題は、速度が遅く、スケーリングしないことです。また、games_teamsテーブルから他のゲーム統計を引き出して、さらに多くのサブクエリを作成する必要があります。

私が試した他の方法は次のとおりです。

望ましくない出力写真

私は次のSQLでそれを達成しました:

SELECT games.game_id, game_name, game_duration, teams.team_id, team_name, team_score
FROM games
INNER JOIN games_teams ON games.game_id = games_teams.game_id
INNER JOIN teams ON games_teams.team_id = teams.team_id

各ゲームに関連するデータが2つの異なるレコードにあるため、この方法でコードを進めるのは難しくなります。行の最初の部分を作成してから、次のループの反復に進み、次の部分を印刷する必要があります。次に、次のゲームのために最初からやり直します。次のように、すべての情報を1行に表示しようとしています。

チームA(スコア45)対チームB(スコア55)、ゲーム時間:5分

だから、すべてが1つのレコードにある方が簡単だと思います。これをうまく達成する方法はありますか?games_teamsテーブルにさらに列が必要な場合もスケーリングしますか?

再作成する必要がある場合は、データベースコードへのペーストビンリンクを次に示します。

どんな助けでも大歓迎です、ありがとう!

4

2 に答える 2

5

次のように、games_teamsとteamsに2回参加する必要があります。

SELECT ga.game_id
        , ga.game_name
        , ga.game_duration
        , t1.team_name, gt1.team_score
        , t2.team_name, gt2.team_score
FROM games ga
JOIN games_teams  gt1 ON gt1.game_id = ga.game_id
JOIN games_teams  gt2 ON gt2.game_id = ga.game_id
JOIN teams t1 ON t1.team_id = gt1.team_id
JOIN teams t2 ON t2.team_id = gt2.team_id
WHERE gt1.team_id < gt2.team_id
        ;

{games_teams * team}サブジョインを絞り出し、それを2回参照するためのクリーンな方法は、CTEに入れることです:(残念ながら、mysqlはCTEをサポートしていません)

WITH gtx AS (
        SELECT gt.game_id
        , gt.team_score
        , te.team_id
        , te.team_name
        FROM games_teams gt
        JOIN teams te ON te.team_id = gt.team_id
        )
SELECT ga.game_id 
        , ga.game_name
        , ga.game_duration
        , g1.team_name, g1.team_score
        , g2.team_name, g2.team_score
FROM games ga
JOIN gtx g1 ON g1.game_id = ga.game_id
JOIN gtx g2 ON g2.game_id = ga.game_id
WHERE g1.team_id < g2.team_id
  ;

結果:

 game_id | game_name | game_duration | team_name | team_score | team_name | team_score 
---------+-----------+---------------+-----------+------------+-----------+------------
       1 | Game A    |           300 | Team A    |         45 | Team B    |         55
       2 | Game B    |           258 | Team C    |         60 | Team D    |         65
(2 rows)
于 2012-06-02T12:53:29.183 に答える
1

これは、次のように UNION を使用して各ゲームのチームを取得できるように、ゲームごとに常に正確に 2 つのチームがあるという事実によって単純化されます。

SELECT q2.game_id, games.game_name, games.game_duration,
       q2.team_id_a, q2.team_id_b,
       teams_a.team_name AS team_name_a,
       teams_b.team_name AS team_name_b,
       games_teams_a.team_score AS team_score_a,
       games_teams_b.team_score AS team_score_b
FROM  (SELECT q.game_id,
              MAX(q.team_id_a) AS team_id_a,
              MAX(q.team_id_b) AS team_id_b
          FROM (
               SELECT games_teams.game_id,
                      MIN(games_teams.team_id) AS team_id_a,
                      0 AS team_id_b
               FROM   games_teams
               GROUP BY games_teams.game_id
            UNION
               SELECT games_teams.game_id,
                      0 AS team_id_a,
                      MAX(games_teams.team_id) AS team_id_b
               FROM   games_teams
               GROUP BY games_teams.game_id
         ) q
        GROUP BY q.game_id) q2
   INNER JOIN games ON q2.game_id = games.game_id
   INNER JOIN teams teams_a ON q2.team_id_a = teams_a.team_id
   INNER JOIN teams teams_b ON q2.team_id_b = teams_b.team_id
   INNER JOIN games_teams games_teams_a ON
              q2.game_id = games_teams_a.game_id AND q2.team_id_a = games_teams_a.team_id
   INNER JOIN games_teams games_teams_b ON
              q2.game_id = games_teams_b.game_id AND q2.team_id_b = games_teams_b.team_id;
于 2012-06-02T13:43:01.187 に答える