在MySQL中选择查询

时间:2014-12-10 16:30:00

标签: mysql

我想选择帖子上发布的总评论。不知何故,我能够做到,但问题是即使帖子上没有评论,总评论也会显示在每个帖子下。

问题:无法获得与发布相关的评论。

我想要的是什么:

选择与每个帖子相关的总评论。

我尝试了什么:

SELECT SUM(total_comment) AS comment 
FROM   user_comment 
       INNER JOIN post 
               ON user_comment.image_id = post.id 
WHERE  status = 0 
    
SELECT SUM(total_comment) AS comment 
FROM   user_comment 
WHERE  status = 0 

这两个查询都会返回所有帖子的所有(总)评论,但我只想显示与特定帖子相关的评论。

My post table

enter image description here

My Comment table

enter image description here

结果看起来像 enter image description here

OR

enter image description here

但我想要

enter image description here

OR enter image description here

更新

我认为大多数人都不明白我想问的是什么?所以我发布了index.php代码,我使用while循环从数据库访问数据,在index.php页面上我想访问特定帖子上发布的总评论。

的index.php

<?php
session_start();
include 'conn.php';
if(!isset($_SESSION['user']))
{
    header('location:signin.php');
}



$smt=$conn->prepare("SELECT * FROM post,images WHERE post.Id=images.Id");
$smt->execute();
$smtt=$conn->prepare("SELECT * FROM post");
$smtt->execute();
$myres=$smtt->fetch(PDO::FETCH_OBJ);
$imgid=$myres->Id;
$imgname=$myres->File_Name;
$qry=$conn->prepare("SELECT SUM(Total_Comment) AS comment FROM user_comment WHERE Image_Id='".$imgid."' AND Image_Name='".$imgname."'");
$qry->execute();
$result=$qry->fetch(PDO::FETCH_OBJ );
$total_coment=$result->comment;
?>
<?php include 'header.php';?>
<?php
if(isset($_SESSION['user']))
{
    include 'nav.php';
}
else
{
    include 'nav-simple.php';
}
?>

    <div class="container-fluid">
    <?php include 'right_sidebar.php';?>
<div class="main-container-top" id="masonry-grid">
    <?php while($rows=$smt->fetch(PDO::FETCH_OBJ)): ?>

        <div class="col-md-3 grid-item post-col">
<img src="image/<?php echo $rows->Image_Name;?>" data-echo="image/<?php echo $rows->Image_Name;?>" class="post-image"/>

            <h5>Post On &nbsp;<?php echo $rows->Post_Date;?> <span class="pull-right">By <?php echo $rows->Post_By; ?></span> <span class="pull-right">Total Comment <?php echo $total_coment;?></span></h5>

            <a href="post-description.php?id=<?php echo $rows->Id ?>"> <h4><?php echo $rows->Post_Title;?></h4> </a>
            <p>
                <?php echo $rows->Post;?>
            </p>

        </div>


    <?php endwhile;?>
</div>
    </div>

<?php include 'footer-content.php';?>
<?php include 'footer.php';?>

更新2

我知道为什么查询在每个帖子下显示2或3的原因是原因是查询从表中选择第一个或第二个id并计算/求和它,但我无法解决问题,因为我想要在每篇文章下发表评论,而不是在所有帖子下发表一条评论。

注意:

当我在后期描述页面上运行查询时,它会正常工作,但我想在index.php页面上显示每篇帖子的总评论数...

我的post-description.php代码

<?php
session_start();
include 'conn.php';
$pic_id='';
if(isset($_GET['id']))
{
    $pic_id=$_GET['id'];
}
$comv=$conn->prepare("SELECT * FROM user_comment WHERE user_comment.Image_Id='".$pic_id."'  AND user_comment.Status=0 AND user_comment.Comment_Status=1");
$comv->execute();
$fimg=$conn->prepare("SELECT Image_Name From Images WHERE Id='".$pic_id."'");
$fimg->execute();
$gimg=$fimg->fetch(PDO::FETCH_OBJ);
$pro=$conn->prepare("SELECT Profile_Picture FROM user_registration WHERE User_Name='".$_SESSION['user']."'");
$pro->execute();
$prof_img=$pro->fetch(PDO::FETCH_OBJ);
$smt=$conn->prepare("SELECT * FROM post,images WHERE post.Id = images.Id AND post.Id='".$pic_id."'");
$smt->execute();
$qry=$conn->prepare("SELECT COUNT(Total_Comment) AS comment FROM user_comment WHERE Status=0 AND Image_Id ='".$pic_id."'");
$qry->execute();
$result=$qry->fetch(PDO::FETCH_OBJ );
$total_coment=$result->comment;
?>
<?php include 'header.php';?>

<?php include 'nav.php';?>

<div class="container-fluid">
    <?php include 'right_sidebar.php';?>
<div class="col-md-1"></div>

    <div class="col-md-9 main-container-top container">
<?php while($rows=$smt->fetch(PDO::FETCH_OBJ)):?>
        <div class="media col-md-12 description-post">


           <img src="image/<?php echo $rows->Image_Name;?>" alt="<?php echo $rows->Image_Name;?>" class="img-rounded img-responsive media-left img-description"/>
            <div class="media-body">
               <h4 class="h4 description-heading"><?php echo $rows->Post_Title;?> <small class="pull-right"><i class="fa fa-comments-o fa-2x"></i> <?php echo $total_coment;?></small></h4>
                <p class="post-text text-justify text-info">

                    <?php echo $rows->Post;?>
            </div>
<?php endwhile;?>
        </div>

        <br/>

            <div class="media col-md-12 comment-section">
<?php
if(isset($_SESSION['comment-error']))
{
?>
    <span class="alert alert-warning col-md-6 container col-md-offset-3"><?php echo $_SESSION['comment-error']; ?></span>
    <?php
}
unset($_SESSION['comment-error']);
 if(isset($_SESSION['comment-success']))
{
?>
    <span class="alert alert-success col-md-6 container col-md-offset-3"><?php echo $_SESSION['comment-success']; ?></span>
    <?php
}
unset($_SESSION['comment-success']);
    ?>
                <br/>



                <?php while($gcom=$comv->fetch(PDO::FETCH_OBJ)):?>
                <span class="col-md-1 comment-pic"><img src="profile%20picture/<?php echo $gcom->Profile_Picture;?>" alt="post image" class="img-thumbnail img-responsive comment-img"/></span>
                <div class="media-body  comment-head col-md-10">
                    <h6 class="h6"><a href="#"> <?php echo $gcom->User_Name;?> </a> on <?php echo $gcom->On_Time;?></h6>
                    <p class="comment"><?php echo $gcom->Comment;?></p>
                </div>
                    <?php endwhile;?>
            </div>

        <br/>
        <div class="col-md-12 container">
            <h4 class="description-heading h4 text-muted">Share your thought</h4>
            <br/>
            <form action="comment.php" method="post" class="col-md-12" id="commentForm">
                <textarea name="comment" id="" cols="100" rows="5" placeholder="Your comment"></textarea>
                <input type="hidden" name='picture-name' value="<?php echo $gimg->Image_Name;?>"/>
                <input type="hidden" name="profile-pic" value="<?php echo $prof_img->Profile_Picture;?>"/>
                <input type="hidden" name="pic-id" value="<?php echo $pic_id;?>"/>
                <input type="hidden" name="image-id" value="<?php echo '?id='.$pic_id;?>"/>
                <br/>
                <input type="submit" value="Post" name="cmsg" id="" class="btn btn-info"/>
                <br/>
            </form>
        </div>
        <br/>



</div>

</div>
<?php include 'footer-content.php';?>
 <?php include 'footer.php';?>

10 个答案:

答案 0 :(得分:2)

如果你为你回来的每个帖子运行一个单独的查询,这就是你想要做的事情,我们只是根据你发布的两个查询进行猜测,这两个查询都返回一行...

要使用该模式,您需要在WHERE子句中添加一个附加谓词,以识别哪个 post您想要返回评论计数。例如:

SELECT SUM(c.total_comment) AS comment
  FROM user_comment c
 WHERE c.status = 0 
   AND c.image_id = 2

如果给定的image_id没有行,则SUM()聚合将返回NULL。您可以在代码中处理它,并将其转换为零,或者您可以在SQL中处理它,以便它将返回零而不是NULL。您可以使用方便的IFULL()功能...

SELECT IFNULL(SUM(c.total_comment),0) AS comment
  FROM user_comment c
 WHERE c.status = 0 
   AND c.image_id = 2

如果IFNULL函数的第一个参数为NULL,则该函数返回第二个参数,否则返回第一个参数。

IFNULL(a,b) 

是ANSI

的特定于MySQL的简写
CASE WHEN a IS NULL THEN b ELSE a END

这回答了你问的问题。如何计算特定职位。


这里的其他答案正在解决这种方法的问题...为每个帖子运行单独的查询并不是最有效或最具可扩展性的设计。

每个查询执行都需要往返数据库,数据库必须解析SQL文本,检查语法是否有效,进行语义检查,字典查找以验证标识符是否有效,数据库用户是否具有所需权限权限,决定执行计划,然后运行查询,准备结果集并返回给调用者。而且这种开销加剧了。

这里的其他一些答案正在解决。他们不是为每个image_id运行单独的查询,而是一举得到计数。他们通过将image_id列添加到SELECT列表并向查询添加GROUP BY image_id来执行此操作...以返回此类结果

image_id  comment
--------  -------
       2        3
       5        2

那会让你回到所有的非零数。但是......你不会在从post表中获取行的循环中运行它...你首先运行这个查询,然后将结果存储到一个数组中,然后对于你正在放置的每个帖子在页面中,您将进行数组查找以查找计数。如果找不到,则计数为零。

您还可以返回零计数,并使用以下查询存储这些计数:

SELECT p.id
     , IFNULL(SUM(total_comment),0) AS comment 
 FROM post p
 LEFT
 JOIN user_comment c 
   ON c.image_id = p.id
  AND c.status = 0
GROUP BY p.id

但那只是额外的行,零,仍然是一个数组查找,唯一的区别是你会找到一个匹配...真的没有什么不同。

但是......你真的不想这样做。

查询真正提示的是,您不需要 SEPRATE 查询来获取评论计数;您可以在 SAME QUERY 中获取该内容,该内容将返回post中的行。

只需将外连接添加到user_comment表,在GROUP BY表中的唯一标识符上添加post子句,并将该聚合SUM()表达式返回到SELECT列表,以及您从post表转向的列。例如:

SELECT p.id
     , p.Post_Title
     , p.Post
     , p.Filename
     , p.Tag
     , p.Post_Date
     , p.Post_By
     , IFNULL(SUM(c.total_comment),0) AS comment 
 FROM post p
 LEFT
 JOIN user_comment c 
   ON c.image_id = p.id
  AND c.status = 0
GROUP BY p.id
ORDER BY p.Post_Date DESC, p.id DESC

这通常是一种更具伸缩性的设计,可以在单个查询中返回结果,而不是运行大量单独的查询。

另一种选择,通常不如外连接那么高效,是在SELECT列表中使用相关子查询:

SELECT p.id
     , p.Post_Title
     , p.Post
     , p.Filename
     , p.Tag
     , p.Post_Date
     , p.Post_By
     , ( SELECT IFNULL(SUM(c.total_comment),0)
           FROM user_comment c
          WHERE c.image_id = p.id
            AND c.status = 0
       ) AS comment
 FROM post p
ORDER BY p.Post_Date DESC, p.id DESC

或者,我们也可以对内联视图使用外连接操作(但是在更一般的情况下,当涉及更多连接时,这更适用,并且我们不希望加倍或三重计数,尽管它在这种情况下会返回相同的结果(假设id表中post是唯一的),

SELECT p.id
     , p.Post_Title
     , p.Post
     , p.Filename
     , p.Tag
     , p.Post_Date
     , p.Post_By
     , IFNULL(t.total_comment,0) AS comment
  FROM post p
  LEFT
  JOIN ( SELECT c.image_id 
              , SUM(c.total_comment) AS total_comment
           FROM user_comment c
          WHERE c.image_id = p.id
          GROUP BY c.image_id
       ) t
    ON t.image_id = p.id
 ORDER BY p.Post_Date DESC, p.id DESC

<强>后续

根据您发布的PHP代码,重点是......您只需要 SINGLE SQL语句。

只需为每个帖子返回派生的“total_comment”值,以及每个帖子行,只需修改查询(正如我在上面的回答中所指出的,有几种可能的方法来获得该结果。只需告诉数据库返回该值相信你。然后你的代码更简单。(为了更确定的结果,在查询中添加ORDER BY子句。)

例如:

$sql="SELECT p.Id
           , p.Post_Title
           , p.Post
           , p.Filename
           , p.Post_Date
           , p.Post_By
           , IFNULL(SUM(c.total_comment),0) AS total_comment
        FROM post p
        LEFT
        JOIN user_comment c 
          ON c.image_id = p.id
         AND c.status = 0
       GROUP BY p.id
       ORDER BY p.Post_Date DESC, p.id DESC"; 

$stmt=$conn->prepare($sql);
$stmt->execute();

while($post = $stmt->fetch(PDO::FETCH_OBJ)):
    echo "<hr>";
    echo "<br>" . $post->Id;
    echo "<br>" . $post->Post_Title;
    echo "<br>" . $post->Post;
    echo "<br>" . $post->Filename;
    echo "<br>" . $post->Post_Date;
    echo "<br>" . $post->Post_By;
    echo "<br>" . $post->total_comment;
endwhile;

这是一个非常简单的示例,只是回显了返回的值,而没有实际想要输出的所有HTML。它用于演示您不需要使用第二个或第三个SQL语句来破解代码。

而且(显然)这个例子没有解决转义存储在数据库列中的潜在HTML字符,也没有解决PDO错误处理,setAttribute(PDO::ATTR_ERRORMODE,PDO::ERRMODE_EXCEPTION)和适当的try / catch / finally块,或者添加单独检查prepareexecute来电的回报。省略了这些以避免模糊模式。

答案 1 :(得分:1)

SELECT SUM(Total_Comment) AS comment FROM user_comment INNER JOIN post ON user_comment.Image_Id = post.Id WHERE Status=0 GROUP BY post.Id

我相信group by inner join可以帮助您获得所需内容。 希望这会有所帮助。

答案 2 :(得分:0)

您需要left joingroup by

对于user_comment

中没有条目的帖子,这将返回零评论
SELECT IFNULL(SUM(Total_Comment),0) AS comments, post.Id FROM 
post
LEFT JOIN user_comment
ON user_comment.Image_Id = post.Id 
AND Status=0
group by post.Id

答案 3 :(得分:0)

如果我理解正确你想要这样的结果啊?

Post 
 totalCommand
Post 
 totalCommand

查询:

SELECT post
FROM (
    SELECT post
        ,postid
        ,1 AS ord
    FROM post

    UNION ALL

    SELECT convert(IFNULL(SUM(Total_Comment), 0), CHAR) AS post
        ,po.postid
        ,2 AS ord
    FROM commenttable co
    RIGHT JOIN posttable po ON po.postid = co.postid
    GROUP BY po.postid
    ) AS tt
ORDER BY postid
    ,ord

答案 4 :(得分:0)

根据其他评论看起来,您已经忘记包含原始查询是在特定用户的评论总数之后。尝试将User_Name添加到WHERE CLAUSE,假设您的代码中某处包含@username变量,但不包括:

SELECT SUM(Total_Comment) AS comment
     , post.Id
FROM user_comment 
INNER JOIN post ON user_comment.Image_Id = post.Id 
WHERE Status=0 
AND user_comments.User_Name = @username
GROUP BY post.Id

答案 5 :(得分:0)

以下是SQLFiddle上带有一些虚拟数据的示例。

但是这样的查询可以获得单个帖子的评论总数。

SELECT COUNT(*) FROM comments INNER JOIN posts ON comments.`Image_Name` = posts.`File_Name` WHERE comments.status = 0 AND comments.Image_Name = "956.jpg";

或者,如果您想获得每篇帖子的评论总数,您将执行以下查询:

SELECT comments.Image_name, COUNT(*) FROM comments INNER JOIN posts ON comments.`Image_Name` = posts.`File_Name` WHERE comments.status = 0 GROUP BY comments.Image_Name;

您可以使用COUNT()代替SUM(),而不再需要Total_Comment列。作为建议,我建议在表之间使用更好的关系(使用ID)。显然,将“956.jpg”更改为您要检查的文件名,或更改要检查的列。

答案 6 :(得分:0)

我并不完全理解在评论表中使用'Total_comment'的目的,可以通过使用'COUNT()'轻松实现。为了简单起见,我将在我的示例中使用COUNT()。

SELECT
    post.Id,
    post.Post_Title,
    post.Post,
    post.File_Name,
    post.Tag,
    post.Post_Date,
    post.Post_By,
    COUNT(user_comment.id) AS total_post_comment
FROM
    post
    LEFT JOIN user_comment ON (user_comment.Image_Id=post.Id AND user_comment.Status=0)
GROUP BY
    post.id

答案 7 :(得分:0)

这对我有用:

select p.*, ifnull(total_comments, 0)
from post p
left join (select image_id, SUM(total_comment) AS total_comments
    from user_comment
    where status = 0
    group by 1) t ON t.image_id = p.id

这将返回所有帖子,对于没有评论(状态为0)的帖子,评论总数为零。

请参阅SQLFiddle

答案 8 :(得分:0)

SELECT 
IFNULL(SUM(c.Total_Comment),0) AS comments, 
post.Id 
FROM 
post p
JOIN user_comment c ON c.Image_Id = p.Id 
AND c.Status=0
group by p.Id

答案 9 :(得分:0)

使用此查询..

SELECT COUNT(*) FROM user_comment INNER JOIN post ON user_comment.Image_Name = post.File_Name WHERE user_comment.Status = 0 AND user_comment.Image_Name = "your image id here";

查询工作正常,如果没有,那么只需改变从mysql获取数据/总评论的方式。