【问题标题】:Sql query (inner join + count + group by) using Propel使用Propel的Sql查询(内连接+计数+分组)
【发布时间】:2009-08-03 13:06:42
【问题描述】:

我想在包含博客文章列表的页面上显示每篇博客文章的 cmets 数量(以及类别、日期、作者等)。我如何在propel中编写以下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 是一个 blog 表和 cmets,一个 cmets 表,其中 post_id 作为 post.id 的外键。我似乎无法将“numofcmets”作为结果集中的一列。目前我正在使用非 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 结果集中访问“numofcmets”?

编辑:我想知道如何在 Propel 中编写上述查询?我现在可以做的是在 cmets 表上获取带有内部连接的 post 表,然后在 cmets 表上为每个 post-id 运行 doCount。这导致对 Post 表的 1 个查询和对 cme​​ts 表的许多查询。我希望将 sql 查询减少到最低限度。 谢谢:)

【问题讨论】:

    标签: mysql symfony1 propel


    【解决方案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. 和更简单的方法,我现在忘记了..)

    【讨论】:

    • 谢谢@nos ...这是我没有正确编写分组查询的基本疏忽,但问题不同。我编辑了……你能再检查一下吗? :)
    【解决方案2】:

    如果您想在自定义查询返回的对象中打包额外数据,您可以覆盖对等类中的默认 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;
    }
    

    【讨论】:

      【解决方案3】:

      这是您的 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。因为。使用内部连接,您只能访问至少有一条评论的帖子。使用左加入,您可以选择未评论的帖子。

      我希望这会有所帮助。

      【讨论】:

      • 我无法访问 $this->posts 中的“numofcmets”。这种方法可能需要定制保湿方法。我不知道该怎么做。
      【解决方案4】:

      嗯,这是行得通的,但这样做是一种可悲的方式:|

      //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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-03-23
        • 1970-01-01
        • 2014-03-01
        • 1970-01-01
        • 1970-01-01
        • 2017-01-31
        • 1970-01-01
        • 2020-03-20
        相关资源
        最近更新 更多