2011-12-03 3 views
3

私はサッカーマネジメントゲームの情報を含む一連のMySQLテーブルを持っています。MySQL maxを使用した詳細の選択

テーブルは、次のとおり

  • プレーヤー - playerID(PK)、プレイヤー名
  • マッチ - matchID(PK)、matchSeason、matchRound、matchType
  • PlayersMatch - playerID、matchID(コンプPK) matchRating、playerForm、playerAge、position(nullも可)

これらの表に格納されているデータは、プレーヤーのパフォーマンスに関連しています。選手は試合でプレーし、定格性能を持つ(matchRating)。プレイヤーが参加している各試合のプレイヤーマッチには、プレーヤーの現在の形式を記録し、試合の時点でのマッチ(過去の目的で)とプレイした位置が記録されます。

現在、現在、私はシーズン全体のトップ10選手をリストするには、次のクエリを使用しています(ラウンドあたりの最高のパフォーマンスではなく、全体としてシーズンで最高の性能):

SELECT playerID, matchID, playerForm, playerAge, MAX(matchRating) 
FROM PlayersMatch 
INNER JOIN Matches ON PlayersMatch.matchID = Matches.matchID 
WHERE Matches.matchSeason = 35 
AND Matches.matchType = 'L' 
AND PlayersMatch.position IS NOT NULL 
GROUP BY PlayersMatch.playerID 
ORDER BY MAX(matchRating) DESC, playerForm ASC 

私は取得しています問題は、しばらくです私は正しいplayerIDとplayer matchRatingを得ています。間違ったmatchID、フォーム、年齢、その他の情報を取得しています(つまり、他のレコードのものです)。

私は正しい情報を得ている間にグループにmatchIDを追加しようとしましたが、playerIDとmatchIDがPlayersMatchのPKを構成するため、プレーヤのために重複したレコードを作成したため重複していました。

あなたのご支援をよろしくお願いいたします。

編集:、さらにいくつか読んだ後、私は間違ってSQLを記述しなければならないとすることによりグループは、私はちょうどplayerIDとmax(matchRating)を持っている場合は、正しい情報を返すために起こっていること - 最低であることをANSI SQLが正しい。

その場合、max/group byを使用している場合、そのパフォーマンスの対応する一致の詳細を取得するにはどうすればよいですか?

編集2:

SELECT * FROM PlayersMatch 
INNER JOIN 
    (SELECT playerID, MAX(matchRating) 
    FROM PlayersMatch p2 
    JOIN Matches 
     ON p2.matchID = Matches.matchID 
    WHERE matchSeason = 35 
    AND matchType = 'L' 
    AND p2.position IS NOT NULL 
    GROUP BY p2.playerID) AS p1 
    ON PlayersMatch.playerID = p1.playerID 
    AND PlayersMatch.matchRating = p1.matchRating 
JOIN Matches m2 
    ON PlayersMatch.matchID = m2.matchID 
WHERE m2.matchSeason = 35 
AND m2.matchType = 'L' 
AND PlayersMatch.position IS NOT NULL 
ORDER BY matchRating DESC 

唯一の問題は、今、それが実行に21秒かかるということである:私は作業のクエリを持っているように見えます。このクエリは正しいか?

+0

私は、トップパフォーマー全体でMAX(マッチレーティング)を使用することに同意しません。 AVGを使用するべきではありませんか?一例として、第1位は10位、第2位は2位(平均6)、プレーヤーBは2位(8,8(平均8))であった。しかし、あなたの計算は、プレーヤーAを最高のパフォーマーにするでしょう。 – ajreal

+0

@ajreal、提案のおかげで、平均的な評価は私が表示しようとしているものではありません。私は平均のために1つを追加するかもしれませんが、この時点では最大値が必要です。しかし、私の問題は解決しません。 :P – Cyntech

+0

あなたはplayerIdとmatchRatingで参加しているわけではありませんが、それは一意であることは保証されていません(matchIdである必要があります)。適切なインデックス(matchRating、おそらくmatchSeason、matchType、およびposition)を作成しましたか? 'explain'を使用して、なぜそれが長くかかるのかを確認してください。 – Inca

答えて

1

MatchModに基づいてPlayersMatchに2番目のインデックスを追加するのは、予選への予備資格の参加のみです。 matchSeasonのMatchesテーブルにインデックスを追加して入力します。

あなたの編集したデータサンプルから、同じ「ランク」の下に複数のスパンを含む最初の「一致」を得ることができると私は考えています。あなたの「MAX()」が明らかに最高の評価を探しているように、もう一度、最も内側のものが最高のMatchRatingを取得します。それから、それは即座にプレーヤーの試合に再参加し、同じ格付けを持つその人物のFIRSTマッチIDを取得します。最後に、それを閉じるために、名前情報のために人物に直接参加することができ、見つかった最初の一致IDに基づいて試合に参加することができるので、重複は返されません...最終結果は試合順位ごとにソートされます。

SELECT STRAIGHT_JOIN 
     Players.PlayerName, 
     M2.*, 
     PM.MatchRating, 
     PM.PlayerForm, 
     PM.PlayerAge, 
     PM.Position 
    FROM 
     (select PreMatch.PlayerID, 
       PreMatch.MaxMatch, 
       MIN(P3.MatchID) as FirstMatch 
      FROM 
       (SELECT 
        p2.playerID, 
        MAX(p2.matchRating) MaxMatch 
       FROM 
        Matches 
         JOIN PlayersMatch P2 
          ON Matches.MatchID = p2.matchID 
         AND P2.Position is not null 
       WHERE 
         Matches.MatchSeason = 35 
        AND Matches.MatchType = 'L' 
       GROUP BY 
        p2.playerID) PreMatch 

       JOIN PlayersMatch P3 
        ON PreMatch.PlayerID = P3.PlayerID 
        AND PreMatch.MaxMatch = P3.MatchRating 
        AND P3.Position is not null 

        JOIN Matches M2 
        on P3.MatchID = M2.MatchID 
        AND M2.MatchSeason = 35 
        AND M2.MatchType = 'L' 
      GROUP BY 
      PreMatch.PlayerID, 
      PreMatch.MaxMatch 
    ) AS p1 

     JOIN Players 
     on P1.PlayerID = Players.PlayerID 

     JOIN PlayersMatch PM 
      on p1.FirstMatch = PM.MatchID 

    ORDER BY 
     p1.MaxMatch DESC 
+0

答えをいただきありがとうございます、それは本当にうまく見えますが、私は各プレイヤーのすべての選手のマッチレコードを取得しています。各プレーヤーのための最もよいmatchRatingにそれを制限するために結合に限界が置かれることができますか? – Cyntech

+0

@ Syntech、どのように私は見ることができないので、これは起こっているそれぞれのテーブルから1人または2人のプレーヤーのためのデータのダンプを行うことができます。最も内側のクエリは1人のプレイヤーにつき1つのレコードしか得られず、シーズン35のLの場合のみマッチレーティングが最大になります。その後、IDでプレイヤーに参加します(1にする必要があります)。同じシーズンのレーティング35、Lを入力します。同じマッチシーズンに複数のエントリーがある場合を除いて、タイプしてマッチする必要はありません。 – DRapp

+0

DRapp、それはまさにその理由です。プレーヤーが同じマッチレーティング(一般的な発生)を持つ場合、そのレーティングを得るたびに1つの行が表示されます。だから私たちは元の問題に戻っています。ここでは、グループに影響するので、結合にmatchIDを追加できません。データの例はhttp://pastebin.com/2ijwPwCc – Cyntech

0

集約は、適用される実際の列でのみ機能します。レコードベースではありません。評価の最大値が選択されますが、他の列の集計方法は決まりません。

だから、レコードを持っている場合:

player 1 | match 1 | 10 
player 1 | match 2 | 5 

、あなたのグループにそれらをプレイヤーによる、それはmatch'フィールドの値を1つのみ選択する必要がありますが、どちらが定義されていません:それはしていません他の列の集約に依存します。

あなたが何をしたいのか、あなたはサブクエリを必要とする場合:私はplayersmatch-テーブル用に生成された主キーを導入しました

SELECT p1.playerID, p1.matchID, p1.playerAge, MAX(p1.matchRating) 
FROM PlayersMatch P1 
JOIN PlayersMatch p2 on p1.id = 
    (SELECT id 
    FROM PlayerMatch p2 
    WHERE p2.playerId = p1.playerId 
    ORDER BY MAX(p2.matchRating) DESC 
    LIMIT 1) 
GROUP BY playerID 

注意(私が参加し、構文のか分からないようコンポジットキーと一般的な単一フィールドの人工キーの場合)。(playerID、matchId)には一意の制約を設定できます。

+0

あなたの提案を試して、それを達成するために生成されたキー(playerID + matchID)を置き換えました。残念ながら、私がそれを殺したとき、つまり実行には20分以上が必要です。 – Cyntech

関連する問題