1

少し背景情報。これは、ユーザーがチャレンジを作成し、それらのチャレンジに投票できるようにするアプリケーションです(標準のuserX-vs-userYタイプのアプリケーション)。

ここでの最終目標は、5人のユーザーのリストを、獲得したチャレンジの数で並べ替えて、一種のリーダーボードを作成することです。ステータス=有効期限が切れており、ユーザーがそのチャレンジに対して50票を超えている場合、ユーザーはチャレンジに勝ちます(チャレンジは合計100票で期限切れになります)。

ここでは少し簡略化しますが、基本的に3つのテーブルがあります。

  1. ユーザー

    • id
    • ユーザー名
    • ..。
  2. 課題

    • id
    • に発行されました
    • が発行
    • 状態
  3. Challenges_votes

    • id
    • Challenge_id
    • ユーザーID
    • 投票済み

これまでのところ、次のような内部クエリがあります。

SELECT `challenges`.`id`
FROM `challenges_votes`
LEFT JOIN `challenges` ON (`challenges`.`id` = `challenges_votes`.`challenge_id`)
WHERE `voted_for` = 1
WHERE `challenges`.`status` = 'expired'
GROUP BY `challenges`.`id`
HAVING COUNT(`challenges_votes`.`id`) > 50

この例では、有効期限が切れており、ID1のユーザーが50票を超えているチャレンジIDを返します。

ここで返される行数をカウントし、usersテーブルから各ユーザーに適用し、返される行数で並べ替えて5つに制限する必要があります。

この目的のために、私は次のクエリを持っています:

SELECT `users`.`id`, `users`.`username`, COUNT(*) AS challenges_won
FROM (
    SELECT `challenges`.`id`
    FROM `challenges_votes`
    LEFT JOIN `challenges` ON (`challenges`.`id` = `challenges_votes`.`challenge_id`)
    WHERE `voted_for` = 1
    GROUP BY `challenges`.`id`
    HAVING COUNT(`challenges_votes`.`id`) > 0
) AS challenges_won, `users`
GROUP BY `users`.`id`
ORDER BY challenges_won
LIMIT 5

どちらがそこにたどり着くのか、もちろんvoted_forここのユーザーIDは常に1です。これはこのタイプのクエリを実行するための正しい方法でさえありますか?誰かが私がそれをどのようにすべきかについて何か光を当てることができますか?

ありがとう!

4

1 に答える 1

5

次のスクリプトで問題が解決すると思います。

-- get the number of chalenges won by each user and return top 5
SELECT usr.id, usr.username, COUNT(*) AS challenges_won
FROM users usr
JOIN (
    SELECT vot.challenge_id, vot.voted_for
    FROM challenges_votes vot
    WHERE vot.challenge_id IN (       -- is this check really necessary?
        SELECT cha.id                 -- if any user is voted 51 he wins, so
        FROM challenges cha           -- why wait another 49 votes that won't
        WHERE cha.status = 'expired'  -- change the result?
    )                                 -- 
    GROUP BY vot.challenge_id
    HAVING COUNT(*) > 50
) aux ON (aux.voted_for = usr.id)
GROUP BY usr.id, usr.username
ORDER BY achallenges_won DESC LIMIT 5;

チャレンジを閉じるための条件について少し考えさせてください。51票後に勝ったユーザーがいる場合、結果が変わらないようにさらに49票待つ必要があるのはなぜですか。この制約を削除できる場合は、challengesテーブルをチェックする必要がなく、クエリのパフォーマンスを向上させることができますが、悪化する可能性もあり、実際のデータベースでテストした後でしかわかりません。

于 2012-05-04T09:05:48.167 に答える