33

私は 2 つの MYSQL テーブル、users、およびscoreを持っています。詳細:

  • ユーザー テーブル:

ここに画像の説明を入力

  • スコア表:

ここに画像の説明を入力

私の意図は、ポイントフィールド ソート DESC (降順) とavg_timeフィールド ソート ASC (昇順) を持つ 20 人のユーザー リストを取得することです。私はクエリを使用します:

SELECT users.username, scores.point, scores.avg_time
FROM scores, users
WHERE scores.user_id = users.id
GROUP BY users.username
ORDER BY scores.point DESC, scores.avg_time
LIMIT 0, 20

結果は次のとおりです。

ここに画像の説明を入力

最初の行は正確に point = 100 および avg_time = 60 であるため、結果は間違っています。

私の望ましい結果は次のとおりです。

username    point    avg_time
demo123      100        60
demo123456   100       100
demo         90        120

さまざまなクエリで何度も試しましたが、結果はまだ間違っています。いくつかの解決策を教えてください。

前もって感謝します!

4

4 に答える 4

29

わかりました、私はあなたが今何を望んでいるのか理解していると思います.クエリの前に確認するために明確にさせてください. ユーザーごとに 1 つのレコードが必要です。各ユーザーについて、BEST POINTS スコア レコードが必要です。ユーザーごとの最高のポイントのうち、平均時間が最高のポイントが必要です。すべてのユーザーの「最高の」値を取得したら、最初に最高のポイントでソートされた最終結果が必要です...ほとんど競争のランキングに似ています。

それでは、クエリです。上記の説明が正しい場合は、1 人あたりの最高ポイント/平均時間を取得し、そのエントリに「ランク」を割り当てることから始める必要があります。これは、MySQL @ 変数を使用して簡単に実行できます。次に、HAVING 句を含めて、各個人のランク 1 のレコードのみを保持します。最後に、ベストポイントと最短平均時間の順序を適用します。

select
      U.UserName,
      PreSortedPerUser.Point,
      PreSortedPerUser.Avg_Time,
      @UserRank := if( @lastUserID = PreSortedPerUser.User_ID, @UserRank +1, 1 ) FinalRank,
      @lastUserID := PreSortedPerUser.User_ID
   from
      ( select
              S.user_id,
              S.point,
              S.avg_time
           from
              Scores S
           order by
              S.user_id,
              S.point DESC,
              S.Avg_Time ) PreSortedPerUser
         JOIN Users U
            on PreSortedPerUser.user_ID = U.ID,
      ( select @lastUserID := 0,
               @UserRank := 0 ) sqlvars 
   having
      FinalRank = 1
   order by
      Point Desc,
      Avg_Time

SQLFiddle によって処理される結果

答えを得るためにインラインの @variables が必要なため、各行の最後に 2 つの余分な列があることに注意してください。これらは単なる「残り」であり、実行しようとしている実際の出力プレゼンテーションでは無視できます...または、全体をもう1レベル上にラップして、必要ないくつかの列を取得することができます

select 
      PQ.UserName,
      PQ.Point,
      PQ.Avg_Time
   from
      ( entire query above pasted here ) as PQ
于 2012-12-04T11:39:11.370 に答える
3

テーブルの関係について理解していないと思います..

ユーザー : スコア = 1 : *

ただjoin解決策ではありません。

これはあなたの意図ですか?

SELECT users.username, avg(scores.point), avg(scores.avg_time)
FROM scores, users
WHERE scores.user_id = users.id
GROUP BY users.username
ORDER BY avg(scores.point) DESC, avg(scores.avg_time)
LIMIT 0, 20

(このクエリは、各ユーザーの平均ポイントと平均 avg_time を desc ポイント asc で取得します) avg_time

各スコアランキングを取得したい場合は?使用するleft outer join

SELECT users.username, scores.point, scores.avg_time
FROM scores left outer join users on scores.user_id = users.id
ORDER BY scores.point DESC, scores.avg_time
LIMIT 0, 20
于 2012-12-04T01:56:05.867 に答える
1

@DRapp は天才です。彼がどのように SQL をコーディングしたのか理解できなかったので、自分の理解でコーディングしてみました。


    SELECT 
      f.username,
      f.point,
      f.avg_time
    FROM
      (
      SELECT
        userscores.username,
        userscores.point,
        userscores.avg_time
      FROM
        (
        SELECT
          users.username,
          scores.point,
          scores.avg_time
        FROM
          scores
        JOIN users
        ON scores.user_id = users.id
        ORDER BY scores.point DESC
        ) userscores
      ORDER BY
        point DESC,
        avg_time
      ) f
    GROUP BY f.username
    ORDER BY point DESC

ユーザー @variables の代わりに GROUP BY を使用しても、同じ結果が得られます。

于 2014-07-02T15:19:41.890 に答える
0

デフォルトでは pk id でグループ化され、結果の
ユーザー名ポイント avg_time
demo123 100 90 ---> id = 4
demo123456 100 100 ---> id = 7
demo 90 120 ---> id = 1

于 2012-12-04T08:36:04.170 に答える