我想在包含博客帖子列表的页面上显示每篇博文的评论数量(以及类别,日期,作者等)。我如何在推进中编写以下mysql查询?
SELECT post.id, post.title, post.more_columns , COUNT(comments.post_id) AS numofcomments FROM post INNER JOIN comments ON post.id = comments.post_id GROUP BY post.id, post.title, post.more_columns
其中post是一个博客表和注释,一个注释表,post_id作为post.id的外键。我似乎无法将'numofcomments'作为结果集中的列。目前我正在使用非ORM方法(这将是我的最后手段):
$con = Propel::getConnection(PostPeer::DATABASE_NAME);
$sql = "SELECT post.* , COUNT(comments.post_id) AS numcomments FROM post INNER JOIN comments ON post.id = comments.post_id GROUP BY post.id";
$stmt = $con->prepare($sql);
$stmt->execute();
$result = PostPeer::populateObjects($stmt);
return $result;
如何在生成的Propel结果集中访问'numofcomments'?
编辑:我想知道的是我如何在Propel中编写上述查询?我现在可以做的是在注释表上获取带有内连接的post表,然后在每个post-id的comments表上运行doCount。这导致1个查询Post表和许多查询表注释。我希望将sql查询减少到最低限度。 谢谢:)
答案 0 :(得分:1)
SELECT post.* , COUNT(comments.post_id) AS numcomments FROM post INNER JOIN comments ON post.id = comments.post_id GROUP BY post.id,post.secondcol,post.thirdcol;
等等,只需列出帖子表中的所有单独列,因为您选择了post。*,您必须全部列出,而不仅仅是post.post_id。
Alternativly
SELECT post.*,sub.numcomments from post,
(select post.post_id as post_id,COUNT(comments.post_id) AS numcomments
FROM post INNER JOIN comments ON post.id = comments.post_id GROUP BY post.id) as sub
where post.post_id = sub.post_id;
(还有一个更简单的方法,我现在忘记了......)
答案 1 :(得分:1)
如果要在自定义查询返回的对象中打包其他数据,可以覆盖对等类中的默认doSelect()方法,并将查询中的其他数据添加到返回的每个对象中。 p>
在你的帖子类中,你可以添加一个受保护的变量,我们称之为“numComments”。
class Post extends BasePost {
protected $numComments;
public function setNumComments($v)
{
$this->numComments = $v;
}
public function getNumComments()
{
return $this->numComments;
}
...
}
然后在你的静态doSelectWithCount()方法的PostPeer类中:
public static function doSelectWithCount() {
$c = new Criteria();
self::addSelectColumns($c); //add all columns from PostPeer
$c->addAsColumn('numofcomments', 'COUNT('.CommentPeer::POST_ID.')');
$c->addJoin(PostPeer::ID, CommentPeer::POST_ID, Criteria::LEFT_JOIN);
$c->addGroupByColumn(PostPeer::ID);
$c->addGroupByColumn(PostPeer::TITLE);
// ...
// more group-by columns if needed
$rs = PostPeer::doSelectRS($c);
$posts = array();
while ($rs->next()) {
$post = new Post();
$post->hydrate($rs);
$post->setNumComments($rs->getInt(PostPeer::NUM_COLUMNS + 1));
$posts[] = $post;
}
return $posts;
}
答案 2 :(得分:0)
这是您的SQL查询的推进版本。
$c = new Criteria();
// count comments with
$c->addAsColumn('numofcomments', 'COUNT('.CommentPeer::POST_ID.')');
$c->addJoin(PostPeer::ID, CommentPeer::POST_ID, Criteria::LEFT_JOIN);
$c->addGroupByColumn(PostPeer::ID);
$c->addGroupByColumn(PostPeer::TITLE);
// you can add more groupby column here
//$c->addGroupByColumn(...more);
$this->posts = PostPeer::doSelect($c);
您应该使用LEFT JOIN而不是INNER JOIN。因为。使用内部联接,您只能访问至少有一条评论的帖子。使用左连接,您可以选择未注释的帖子。
我希望这会有所帮助。
答案 3 :(得分:0)
这是有效的,但这是一种令人难过的方式:|
//inside a static function in class PostPeer:
$c = new Criteria();
self::addSelectColumns($c); //add all columns from PostPeer
$c->addJoin(PostPeer::ID, CommentPeer::POST_ID, Criteria::LEFT_JOIN);
$cu->addAsColumn('numofcomments', 'COUNT('.CommentPeer::POST_ID.')');
$cu->addGroupByColumn(PostPeer::ID);
$cu->addGroupByColumn(PostPeer::TITLE);
:
:
//more group-by columns if needed
return PostPeer::doSelectStmt($c);
然后在模板中我将数组访问为:
<div id="title">
<?php echo post_array[1] ?>
</div>
//...and so on for other Post fields
如何在模型中建立数组关联,以便我可以在模板中编写“post_array ['title']”而不是“post_array [1]”? 此外,这种解决方法是否安全?任何更好的建议。我正在使用Propel 1.3