1

在我目前工作的网站上,有一个类似于本网站的评分系统,每个客户都可以累积“积分”或“星星”。

现在我正在开发一个自动电子邮件系统,它将发送我所有用户的前 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 行加上特定用户的 1 行,如果该用户不属于前 5 个顶部行。这可以通过子查询来实现:

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 回答