0

私たちのプロジェクトでは、名前とさまざまな種類のスコア (全体的なスコア、クエスト スコアなど) を含むユーザーデータが格納されているユーザー テーブルがあります。値がどのように計算されるかは問題ではありませんが、それらは分離されたものとして取ります。

以下のようにテーブル「users」を見てみましょう

  id   name   score_overall   score_trade   score_quest    

  1    one    40000           10000         20000
  2    two    20000           15000         0
  3    three  30000           1000          50000
  4    four   80000           60000         3000

スコアを表示するために、ダミーのテーブルと、スコアの種類ごとに 1 つのテーブルがあり、ここにはユーザー名がポイント スコアとランクと共に格納されます。すべてのテーブルは同じように見えますが、名前が異なります。

id  name  score  rank  

これらは、ユーザーがテーブルを検索およびフィルタリングできるように分離されています。ランク 60 のプレーヤー "playerX" の行が 1 つあるとします。したがって、"playerX" のスコアをフィルター処理すると、この行のみが表示されますが、ランク 60 です。つまり、ランクは「ハード ストア」されているだけでなく、行番号などを介して動的に表示されます。

さまざまなスコア テーブルは、次のことを行う cronjob を介して (および追加のダミー テーブルを使用して) 埋められます。

  1. ユーザーデータをダミーテーブルにコピーします
  2. ダミーテーブルを変更しますorder by score
  3. ダミー テーブルを特定のスコア テーブルにコピーして、AI の主キー (ランク) に各ユーザーのランクを表す適切な値が自動的に入力されるようにします。

つまり、5 つの特定のスコアがある場合は、5 つのスコア テーブルとダミー テーブルもあり、合計 6 になります。

最適化する方法は?

私がやりたいことは、すべてを最適化し、重複するテーブルを削除して (可能であればダミー テーブルを避けて)、次の列を持つ 1 つのテーブルにすべてのスコア データを格納することです。

userid, overall_score, overall_rank, trade_score, trade_rank, quest_score, quest_rank

私の質問は、どうすればこれを最善の方法で行うことができるかということです。上記のような別の方法がありますか (すべての異なるテーブルを使用)。MYSQL ステートメントおよび/または php コードは大歓迎です。少し前に行番号を使用しようとしましたが、これは機能しません。a) 挿入ステートメントで使用できないため、b) すべてのプレーヤー (上記の例の「playerX」など) をフィルタリングすると、ランク 1 になるためです。返される唯一の行です。

4

1 に答える 1

0

さて、次の構成でテーブルを作成してみてください。

id | name | score_overall | score_trade | score_quest | overall_rank | trade_rank | quest_rank

その場合、次のクエリを使用してテーブルにデータを入力できます。

SET @overall_rank:=-(SELECT COUNT(id) FROM users);
SET @trade_rank:=@overall_rank;
SET @quest_rank:=@overall_rank;

SELECT *
FROM users u
INNER JOIN (SELECT id,
                   @overall_rank:=@overall_rank+1 AS overall_rank
            FROM users
            ORDER BY score_overall DESC) ovr
ON u.id = ovr.id
INNER JOIN (SELECT id,
                   @trade_rank:=@trade_rank+1 AS trade_rank
            FROM users
            ORDER BY score_trade DESC) tr
ON u.id = tr.id
INNER JOIN (SELECT id,
                   @quest_rank:=@quest_rank+1 AS quest_rank
            FROM users
            ORDER BY score_quest DESC) qr
ON u.id = qr.id
ORDER BY u.id ASC

SQL フィドルを用意しました。

レコードをたくさん獲得し始めると、パフォーマンスが重くなると思いますが。

ちょっとした説明:@*_rankものは SQL 変数です。新しい行ごとに 1 ずつ増加します。

于 2013-09-15T17:58:57.937 に答える