1

我想在包含博客文章列表的页面上显示每篇博客文章的评论数量(以及类别、日期、作者等)。我如何在推进中编写以下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 中编写上述查询?我现在可以做的是在评论表上获取带有内部连接的帖子表,然后在每个帖子 ID 的评论表上运行 doCount。这导致对 Post 表的 1 个查询和对 comments 表的许多查询。我希望将 sql 查询减少到最低限度。谢谢 :)

4

4 回答 4

1

如果要在自定义查询返回的对象中打包额外数据,可以覆盖对等类中的默认 doSelect() 方法,并将查询中的这些额外数据添加到返回的每个对象中。

在您的帖子类中,您可以添加一个受保护的变量,我们称之为“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;
}
于 2009-08-06T22:20:19.973 回答
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.post_id。

或者

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;

(还有一个 3. 和更简单的方法,我现在忘记了..)

于 2009-08-03T17:57:16.973 回答
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。因为。使用内部连接,您只能访问至少有一条评论的帖子。使用左加入,您可以选择未评论的帖子。

我希望这有帮助。

于 2009-08-04T17:14:38.590 回答
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

于 2009-08-05T13:45:27.047 回答