1

私が現在取り組んでいる Web サイトには、このサイトと同様の評価システムがあり、各クライアントは「ポイント」または「スター」を貯めることができます。

現在、ユーザーの上位 5 リストとそのスコアをすべて送信し、上位 5 リストと並べて、受信者ユーザーの個人スコアも送信する自動電子メール システムに取り組んでいます。

これはサーバー(cronjob)での日常的なタスクであるため、効率の側面が非常に重要です。各ユーザーの評価を取得するために mySql 変数を使用しています。

同じクエリを使用して、他のユーザーとその評価 (100 位であっても) を取得しようと考えましたが、何らかの理由で正しい結果が得られません。

作業コード:

    private function getTopStars($adminId){
        try{
            $conn = DBLink::getInstance();
            $query = "SELECT @rownum:=@rownum+1 AS rank, u.user_id, u.contact_name AS name, p.points  FROM scores p, (SELECT @rownum:=0) r, users u WHERE u.stars_enabled = 1 and u.user_id=p.user_id and p.admin_id = :admin_id AND u.user_id <> :adminId ORDER BY points DESC";
            $sth = $conn->prepare($query);
            $sth->bindParam(':adminId', $adminId, PDO::PARAM_INT);
            $sth->execute();
            $topStars = $sth->fetchAll(PDO::FETCH_ASSOC);
            $html = '';
            foreach($topStars as $topStar){
                $html .= " <div class='score'>
                         <div style='float:left;padding:2px;' class='rank'> " .
                        $topStar['rank'] . "# </div><div style='float:left;padding:2px;font-size: 12px;'>" . $topStar["name"] . " </div><div style='float:left;padding:2px;font-size: 11px;'> ( " . $topStar["points"]. " <img src='http://mydev.com/images/star_icon.jpg' /> )</div></div><br style='clear:both;'/>";
            }
            return $html;

        }   
         catch(PDOException $err){...}
}

動作を拒否する追加:

private function getTopStars($adminId, $userId){
        try{
            $conn = DBLink::getInstance();
            $query = "SELECT @rownum:=@rownum+1 AS rank, u.user_id, u.contact_name AS name, p.points  FROM scores p, (SELECT @rownum:=0) r, users u WHERE u.stars_enabled = 1 and (u.user_id=p.user_id and p.admin_id = :admin_id) OR (u.user_id = :uid) AND u.user_id <> :adminId ORDER BY points DESC";
            $sth = $conn->prepare($query);
            $sth->bindParam(':adminId', $adminId, PDO::PARAM_INT);
            $sth->bindParam(':uid', $userId, PDO::PARAM_INT);
            $sth->execute();
            $topStars = $sth->fetchAll(PDO::FETCH_ASSOC);
            $html = '';
            foreach($topStars as $topStar){
                $html .= " <div class='score'>
                         <div style='float:left;padding:2px;' class='rank'> " .
                        $topStar['rank'] . "# </div><div style='float:left;padding:2px;font-size: 12px;'>" . $topStar["name"] . " </div><div style='float:left;padding:2px;font-size: 11px;'> ( " . $topStar["points"]. " <img src='http://mydev.com/images/star_icon.jpg' /> )</div></div><br style='clear:both;'/>";
            }
            return $html;

        }   
         catch(PDOException $err){...}
}

この方法で機能させることができない場合に私ができる唯一のことは、グループ化と数学SQL関数を使用して各ユーザーの個人情報を取得する別のプライベートメソッドを実装して、スコアで彼の評価を取得することですサーバーリソースの無駄だと思います。

クエリのロジック: 現時点でランキング上位の 5 人のユーザーを受信したいと考えています。これらのユーザーは、(変数を使用して) 順位付けされ、ラベルが付けられています。ランキング表から管理者を除外したい。なぜうまくいかないのですか?スコア列などにインデックスを付ける必要がありますか。

助けてくれてありがとう!

4

1 に答える 1

1

これは、「作業中」と説明する選択です

SELECT @rownum:=@rownum+1 AS rank, u.user_id, u.contact_name AS name, p.points  
FROM scores p, (SELECT @rownum:=0) r, users u 
WHERE u.stars_enabled = 1 
  AND u.user_id=p.user_id 
  AND p.admin_id = :admin_id 
  AND u.user_id <> :adminId 
ORDER BY points DESC

これは、「機能していない」と説明する選択です

SELECT @rownum:=@rownum+1 AS rank, u.user_id, u.contact_name AS name, p.points  
FROM scores p, (SELECT @rownum:=0) r, users u 
WHERE  u.stars_enabled = 1 
  AND (u.user_id=p.user_id AND p.admin_id = :admin_id) 
  OR  (u.user_id = :uid) 
  AND  u.user_id <> :adminId 
ORDER BY points DESC

MySQL では、「AND」は「OR」よりも優先順位が高く、WHERE 条件は次のように評価されます。

(u.stars_enabled = 1 AND u.user_id=p.user_id AND p.admin_id = :admin_id)
OR  
(u.user_id = :uid AND  u.user_id <> :adminId )

これはおそらくあなたが望んでいたことではありませんが、あなたが達成しようとしていることを実際には理解していません。

あなたの説明によると、「私は他のユーザーを取得しようと思いました....」 あなたが実際に何をしようとしているのかについては、私は大雑把な推測しかできません。最初のクエリ (作業中のクエリ) は、特定の admin_id に関連付けられているすべてのユーザーのリストを提供するため、参照している「他のユーザー」を含める必要がありますか? いいえ?

編集

私は今あなたの質問を理解していると思います。あなたが話している追加のユーザーは、すでにそのランキングの一部です。あなたがやろうとしているのは、特定のユーザーが上位 5 行に含まれていない場合に、クエリを 5 行に加えて1 行に制限する方法です。これは、サブクエリで実現できます。

SELECT * FROM (
    SELECT @rownum:=@rownum+1 AS rank, u.user_id, u.contact_name AS name, p.points  
    FROM scores p, (SELECT @rownum:=0) r, users u 
    WHERE u.stars_enabled = 1 
      AND u.user_id=p.user_id 
      AND p.admin_id = :admin_id 
      AND u.user_id <> :adminId 
    ORDER BY points DESC
) WHERE rank<=5 or u.user_id=:uid
于 2013-04-20T20:27:34.067 に答える