简体   繁体   English

单个查询用于多个sql查询

[英]single query for multiple sql queries

I am working on a project where a user can add comments and also hit any post. 我正在开发一个项目,用户可以在其中添加评论,也可以点击任何帖子。

Now I have to display the total number of comments and total number of hits and also show whether the user has already hitted that post or not. 现在,我必须显示评论总数和点击总数,还必须显示用户是否已经点击了该帖子。

So basically I need to do three sql queries for this action: 因此,基本上,我需要为此操作执行三个sql查询:

  • one counting comments, 一个计数的评论,
  • one for counting hits and 一个用于计算点击数和
  • one for checking whether the user has hitted the post or not. 一种用于检查用户是否点击了帖子。

I wanted to know that if it's possible to reduce these three sql queries into one and reduce the database load? 我想知道是否有可能将这三个SQL查询减少为一个并减少数据库负载?

Any help is appreciated. 任何帮助表示赞赏。

$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

This query returns the number of hits and number of nonempty comments. 该查询返回命中数和非空注释数。

select ifnull(sum(hit='hit'),0) as hits, ifnull(sum(comment !=''),0) as comments 
  from fk_views where onid='$postid' and email='$email'

Based on the queries you provided I dont think you need to query separately if he is hitted the post, just check in you code if number of hits is > 0 根据您提供的查询,我认为您是否需要分别查询他是否被点击,只需在您的代码中检查点击数是否大于0

Yes, it may be possible to combine the three queries into a single query. 是的,可以将三个查询合并为一个查询。 That may (or may not) "reduce the database load". 这可能会(也可能不会)“减少数据库负载”。 The key here is going to be an efficient execution plan, which is going to primarily depend on the availability of suitable indexes. 这里的关键是制定有效的执行计划,该计划主要取决于合适索引的可用性。

Combining three inefficient queries into one isn't going to magically make the query more efficient. 将三个低效率的查询合并为一个查询不会神奇地提高查询的效率。 The key is getting each of the queries to be as efficient as they can be. 关键是使每个查询尽可能高效。

If each of the queries is processing rows from the same table, then it may be possible to have a single SELECT statement process the entire set, to obtain the specified result. 如果每个查询正在处理同一表中的行,则可能有一个SELECT语句处理整个集合,以获得指定的结果。 But if each of the the queries is referencing a different table, then it's likely the most efficient would be to combine them with a UNION ALL set operator. 但是,如果每个查询都引用一个不同的表,则最有效的方法可能是将它们与UNION ALL集运算符组合在一起。

Absent the schema definition, the queries that you are currently using, and the EXPLAIN output of each query, it's not practical to attempt to provide you with usable advice. 缺少架构定义,当前正在使用的查询以及每个查询的EXPLAIN输出,尝试为您提供可用的建议是不切实际的。


UPDATE 更新

Based on the update to the question, providing sample queries... we note that two of the queries appear to be identical. 根据问题的更新,提供示例查询...我们注意到其中两个查询似乎是相同的。

It would be much more efficient to have a query return a COUNT() aggregate, than pulling back all of the individual rows to the client and counting them on the client, eg 使查询返回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'

To combine processing of the three queries, we can use conditional expressions in the SELECT list. 为了结合三个查询的处理,我们可以在SELECT列表中使用条件表达式。 For example, we could use the equality predicates on the onid and email columms in the WHERE clause, and do the check of the hit column with an expression... For example: 例如,我们可以在WHERE子句中的onidemail列上使用相等谓词,并使用表达式对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'

The "trick" to getting three separate queries combined would be to use a common set of equality predicates (the parts of the WHERE clause that match in all three queries). 组合三个独立查询的“技巧”将是使用一组通用的相等谓词(在所有三个查询中都匹配的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'

If we are going to insist on using the deprecated mysql interface (over PDO or mysqli) it's important that we use the mysql_real_escape_string function to avoid SQL Injection vulnerabilities 如果我们要坚持使用不推荐使用的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'];
}

For performance, we'd likely want an index with leading columns of onid and email , eg 为了提高性能,我们可能希望索引包含onidemail的前onid列,例如

... ON fk_views (onid,email)

The output from EXPLAIN will show the execution plan. EXPLAIN的输出将显示执行计划。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM