3

私は検索して検索しましたが、これを機能させることができませんでした。誰かが私を助けてくれたら本当にありがたいです。

プレイしたゲームの情報を格納するテーブルがあります (小さなクイズ アプリケーション)。 最高スコアと最低タイムに基づいて、上位 5 人のプレイヤーを決定できるようにする必要があります。(多くのプレーヤーは最大スコアを持っています)。また、いつでもユーザーのランクを判断する必要があります。

以下は、ゲーム テーブルのサンプルです。

user_id クレジット time_played エイリアス
------- ------- ----------- --------------
64 490 180 ダプラヤ
93 690 187 スーパーマン
64 336 187 ダプラヤ
75 196 192 フレーク
93 182 197 スーパーマン
57 844 198 ジョン・スミス
75 350 198 フレーク
64 858 384 ダプラヤ
73 858 400 リトルガイ
57 858 412 ジョン・スミス
101 858 420 フラッシュ
73 858 423 リトルガイ
73 858 434 リトルガイ
65 858 460 シーナ
122 858 540 シュガー クイーン
126 858 545 レイチェル
176 350 2417 ファイヤーライト
157 350 2442 ビッグ Q
161 350 2456 ジョーイ・ブルー

私が使用している現在のクエリは次のとおりです。

select top 5 alias,user_id, 
   rank() over (order by max(credits) desc,min(time_played)) as rank 
from games,users 
where games.user_id=users.id and users.id <> 20 and games.credits > 0 
group by user_id,alias

(クエリからわかるように、エイリアスは実際には users テーブルに格納されています。)

正しい結果が表示されているように見えたので、このクエリは機能していると思いましたが、サイトが公開され、何千ものゲームがあるので、それが間違っていることがわかります。

上記のクエリでは、基本的にスコアが最も高い 5 人のプレイヤーが得られますが、ゲーム時間が最も短いプレイヤーがランク付けされます。(スコアが低いほど速いゲーム)。

このクエリを微調整/変更する方法、または完全に書き直す方法を教えてください。

(注意してください、これは php とループを使用してもっと簡単に行うことができますが、あまり効率的ではありません。)

必要に応じて、さらに情報を提供させていただきます。

前もってありがとう、アーロン。

4

4 に答える 4

3
with user_ranked_games as (
  select user_id,
         credits,
         time_played,
         row_number() over (  partition by user_id 
                              order by credits desc, time_played asc
                           ) as game_rank
    from games
)
select top 5
       rank() over (order by g.credits desc, g.time_played asc) as rank,
       g.user_id,
       u.alias,
       g.credits,
       g.time_played
  from user_ranked_games g
  join users u
    on g.user_id = u.user_id
 where g.game_rank=1
order by rank

上記をSQL Fiddleで正常にテストしました。データ値を変更して、littleguy が上位 5 つのスコアのうち 2 つになるようにしました。しかし、上記のクエリでは、ランク付けされた上位 5 人のプレーヤーの中で、littleguy が正しくリストされているのは 1 回だけです。

注 - 私の元の SQL フィドルには重複したユーザー行があり (私は PK を定義しませんでした)、結合が行われた場所に応じて異なる出力につながりました。それ以来、データを修正し、結合を CTE から削除して、最初に意図したとおりに最も外側のクエリに配置しました。

コメントに応じて更新

小さな変更により、個々のユーザーのユーザー ランクとスコアを検索できるクエリが提供されます。

with user_ranked_games as (
  select user_id,
         credits,
         time_played,
         row_number() over (  partition by user_id 
                              order by credits desc, time_played asc
                           ) as game_rank
    from games
),
ranked_users as (
  select rank() over (order by g.credits desc, g.time_played asc) as rank,
         g.user_id,
         u.alias,
         g.credits,
         g.time_played
    from user_ranked_games g
    join users u
      on g.user_id = u.user_id
   where g.game_rank=1
)
select * from ranked_users where user_id=93

両方の質問に答えるために便利に使用できるビューを作成することを検討してください。

create view ranked_users as
with user_ranked_games as (
  select user_id,
         credits,
         time_played,
         row_number() over (  partition by user_id
                              order by credits desc, time_played asc
                           ) as game_rank
    from games
),
select rank() over (order by g.credits desc, g.time_played asc) as rank,
       g.user_id,
       u.alias,
       g.credits,
       g.time_played
  from user_ranked_games g
  join users u
    on g.user_id = u.user_id
 where g.game_rank=1

最初のクエリは次のようになります。

select top 5 * from ranked_users order by rank

そして、2番目のクエリは次のようになります

select * from ranked_users where user_id=93
于 2012-07-12T04:38:56.297 に答える
1

スコアが最も高く、次にタイムが低いプレイヤーのランクが必要な場合は、次を使用します。

select 
    topalias,
    user_id, 
    rank() OVER (ORDER BY Credits DESC, timePlayed ASC) AS Rank
from 
    games
    INNER JOIN users 
        on games.user_id = users.id 
 Order By 
     Credits DESC, timePlayed ASC
于 2012-07-11T22:25:24.283 に答える
0

複雑な要因は、(私が正しく理解している場合)各プレーヤーが(たとえば)5つの最高スコアを持っている場合でも、各プレーヤーに1回だけ表示したいということです。したがって、最初にすべてのゲームをランク付けし、次に各プレーヤーに最適なゲームを取得してから、これらの上位5つの詳細を取得する必要があります。

CREATE TABLE #Games
    (
    GameID  INT NOT NULL PRIMARY KEY,
    UserID  INT NOT NULL,
    Rank    INT NOT NULL,
    )
INSERT INTO #Games (GameID, UserID, Rank)
    SELECT
        game_id, user_id, ROW_NUMBER() OVER (ORDER BY credits DESC, time_played) AS Rank
    FROM
        games

SELECT TOP 5
    U2.alias, G2.credits, G2.time_played
FROM
    (
    SELECT UserID, MIN(Rank) AS BestRank
    FROM #Games
    GROUP BY UserID
    ) AS U1
    INNER JOIN users AS U2 ON U1.UserID = U2.user_id
    INNER JOIN #Games AS G1 ON U.BestRank = G1.Rank
    INNER JOIN games AS G2 ON G1.GameID = G2.game_id
ORDER BY
    U1.BestRank
于 2012-07-11T22:58:37.260 に答える
0

私はあなたの SELECT 句に少し混乱していることを認めますが... GROUP BY 句の後に「ORDER BY credits DESC, time_played ASC」を入れるだけだと思います。そして、おそらく SELECT * だけです。

5 つの異なる名前を保証するソリューションが必要な場合は、FROM 句を変更して、そのテーブルから個別の名前を含むテーブルを取得します。

于 2012-07-11T22:25:11.660 に答える