2012-05-03 12 views
0

背景情報のビット。これはユーザーが課題を作成し、その課題に投票できるようにするアプリケーションです(標準のuserX-vs-userYタイプのアプリケーション)。MySQLネストされたクエリカウント

最後の目標は、リーダーボードの種類を作成するために、獲得したチャレンジの数でソートされた5人のユーザーのリストを取得することです。ステータスが期限切れで、ユーザーがそのチャレンジに対して50以上の票を得た場合(チャレンジは100回の投票の後に終了する)、チャレンジはユーザーによって獲得されます。

私は少しここでは、物事を単純化しますが、基本的に3つのテーブルがあります。

  1. ユーザー

    • ID
    • ユーザ名
    • ...
  2. チャレンジ

    • ID
    • issued_to
    • ステータス
    • issued_by
  3. challenges_votes

    • ID
    • をchallenge_id

voted_for

  • のuser_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 
    

    をID 1の投票権は> 50です。

    私は何をする必要があることは、行数がここで返された回数のユーザーテーブルから各ユーザーにそれを適用する、返される行の数でこれを注文し、そのためには5

    に制限されるI次のクエリを持っている:

    ちょっとそこなったが、もちろん、ここでvoted_forユーザーIDは常に1です
    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 
    

    が、これはこのタイプの問合せについて移動するにも正しい方法ですか?どのように私はそれをやっている必要がありますについて誰も光を当てることができますか?

    ありがとうございます!

  • +0

    こんにちは、あなたのテーブル構造についての詳細を教えてください。私は 'challeng_votes'にuser_idがあると思っていましたが、あなたの質問でそれを見つけることはできません。 –

    +0

    'challeng_votes'のvoted_for列は投票者のユーザーIDですが、user_idは投票自体を行ったユーザーのIDです(このクエリでは関係ありません)。 – paulbennett

    答えて

    3

    私は次のスクリプトは、あなたの問題を解決すると思います:

    -- 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テーブルをチェックする必要がなくなり、クエリのパフォーマンスが向上する可能性がありますが、実際のデータベースでテストした後でしか知ることはできません。

    +0

    パーフェクト - ありがとう!私たちは、合計100票に達するまで挑戦を開いたままにしておきます。その結果、ある時点でユーザー1人につき合計票数をカウントすることができます。 – paulbennett