我正在开发一个用户可以添加评论并点击任何帖子的项目。
现在我必须显示评论总数和总点击次数,并显示用户是否已经发过该帖子。
所以基本上我需要为这个动作做三个sql查询:
我想知道如果可以将这三个sql查询减少为一个并减少数据库负载吗?
感谢任何帮助。
$checkifrated=mysql_query("select id from fk_views where (onid='$postid' and hit='hit' and email='$email')");//counting hits
$checkiffollowing=mysql_query("select id from fk_views where (onid='$postid' and hit='hit' and email='$email')");
$hitcheck=mysql_num_rows($checkifrated);//checking if already hited or not
$checkifrated=mysql_query("select id from fk_views where (onid='$postid' and comment !='' and email='$email')");//counting comments
答案 0 :(得分:2)
此查询返回命中数和非空注释数。
select ifnull(sum(hit='hit'),0) as hits, ifnull(sum(comment !=''),0) as comments
from fk_views where onid='$postid' and email='$email'
根据您提供的查询,我不认为您需要单独查询是否有帖子,只需检查您的代码是否有点击次数> 0
答案 1 :(得分:1)
是的,可以将三个查询合并为一个查询。这可能(或可能不)“减少数据库负载”。这里的关键是一个有效的执行计划,主要取决于合适索引的可用性。
将三个低效的查询合并为一个不会神奇地使查询更有效。关键是让每个查询尽可能高效。
如果每个查询正在处理来自同一个表的行,则可能有一个SELECT语句处理整个集合,以获取指定的结果。但是,如果每个查询都引用了不同的表,那么最有效的方法是将它们与UNION ALL集合运算符组合在一起。
如果没有架构定义,您当前使用的查询以及每个查询的EXPLAIN输出,那么尝试为您提供有用的建议是不切实际的。
<强>更新强>
根据问题的更新,提供示例查询......我们注意到其中两个查询看起来完全相同。
让查询返回COUNT()
聚合比将所有单独的行拉回到客户端并在客户端上计算它们会更有效,例如
SELECT COUNT(1) AS count_hits
FROM fk_views v
WHERE v.onid = '42'
AND v.hit = 'hit'
AND v.email = 'someone@email.address'
要组合三个查询的处理,我们可以在SELECT列表中使用条件表达式。例如,我们可以在WHERE子句中的onid
和email
列上使用等式谓词,并使用表达式检查hit
列...
例如:
SELECT SUM(IF(v.hit='hit',1,0)) AS count_hits
, SUM(1) AS count_all
FROM fk_views v
WHERE v.onid = '42'
AND v.email='someone@email.address'
将三个单独的查询组合在一起的“技巧”是使用一组通用的等式谓词(在所有三个查询中匹配的WHERE子句的部分)。
SELECT SUM(IF(v.hit='hit' ,1,0)) AS count_hits
, SUM(IF(v.comment!='',1,0)) AS count_comments
, SUM(1) AS count_all
FROM fk_views v
WHERE v.onid = '42'
AND v.email ='someone@email.address'
如果我们要坚持使用已弃用的mysql接口(通过PDO或mysqli),重要的是我们使用 mysql_real_escape_string
函数来避免SQL注入漏洞
$sql = "SELECT SUM(IF(v.hit='hit' ,1,0)) AS count_hits
, SUM(IF(v.comment!='',1,0)) AS count_comments
, SUM(1) AS count_all
FROM fk_views v
WHERE v.onid = '" . mysql_real_escape_string($postid) . "'
AND v.email = '" . mysql_real_escape_string($email) ;
# for debugging
#echo $sql
$result=mysql_query($sql);
if (!$result) die(mysql_error());
while ($row = mysql_fetch_assoc($result)) {
echo $row['count_hits'];
echo $row['count_comments'];
}
为了提高性能,我们可能需要一个前导列为onid
和email
的索引,例如
... ON fk_views (onid,email)
EXPLAIN
的输出将显示执行计划。