0

ランキングのハードコーディングが必要なプロジェクトに取り組んでいます (正規化のコメントはありません)。この例には、スコアの表があります。各スコア レコードは、個人とゲームの特定の繰り返しに関連しています。人はある時点で自分のスコアを破り、複数の記録を持つ可能性があるため、ゲームのその特定の繰り返しでの最高スコアをランク付けしたいだけです。次のクエリは、個別にランク付けできるように、特定のゲーム イテレーションで各個人の最高スコアをマークするために使用されています。

以下は非常に遅いので、スピードアップしたい:

/* Define a game iteration */
SET @VarID=(can be any number from 1-200k);

/* WITHIN A game iteration RESET ALL OF THE PERSONAL BEST */

UPDATE scores m
SET m.personal_best='0'
WHERE VarID = @VarID;

/* IDENTIFY THE "BEST" (in this case the highest score per PeopleID) */

UPDATE scores m
SET m.personal_best='1'
WHERE m.ScoreID IN 
(
    SELECT _scoreID
    FROM
    (   
        SELECT ScoreID as _scoreID FROM scores WHERE VarID = @VarID AND NewScore = ( select max(NewScore) from scores i where i.PeopleID = scores.PeopleID AND VarID = @VarID ) ORDER BY VarID, NewScore DESC   
    ) s

) AND VarID = @VarID;
4

1 に答える 1

0

これは、MySQL のマルチテーブル UPDATE 構文を使用して、サブクエリなしで実行できます。

OUTER JOIN を使用して、同じ人物と varid のスコア、およびより高いスコアを探します。より高いスコアが見つからない場合 (つまり、mが最高スコアの行である場合)、外部結合は結合されたテーブルのすべての列を NULL にします。

UPDATE scores m
LEFT OUTER JOIN scores AS better
  ON m.VarID = better.VarID AND m.PeopleID = better.PeopleID 
  AND m.NewScore < better.NewScore
SET m.personal_best='1'
WHERE VarID = @VarID
  AND better.VarID IS NULL;

しかし、関係があるかもしれません。その人が最高のスコアを複数回達成した場合、複数の行が最高のスコアとしてマークされます。これを回避したい場合は、一意であることが保証されている他の列を使用して関係を断つ必要があります。

UPDATE scores m
LEFT OUTER JOIN scores AS better
  ON m.VarID = better.VarID AND m.PeopleID = better.PeopleID 
  AND (m.NewScore < better.NewScore OR m.NewScore = better.NewScore AND m.ScoreID < better.ScoreID)
SET m.personal_best='1'
WHERE VarID = @VarID
  AND better.VarID IS NULL;
于 2013-07-02T18:43:00.010 に答える