2009-08-03 28 views
1

查詢(inner join + count + group by)我想在包含博客文章列表的頁面上顯示每篇博文的評論數(以及類別,日期,作者等)。我如何在propel中編寫下面的mysql查詢?使用Propel

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; 

我如何才能獲得「numofcomments」在所得到的結果集的Propel?

編輯:我想知道的是我如何在Propel中編寫上述查詢?我現在可以做的是在評論表上使用內部連接來獲取帖子表,然後在每個帖子ID的評論表上運行doCount。這將導致Post表和查詢表的許多查詢有1個查詢。我希望將sql查詢減少到最少。 謝謝:)

回答

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 [‘標題’]」的模板,而不是「 post_array [1]「? 此外,此解決方案是否安全?任何更好的建議。我正在使用Propel 1.3

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_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; 

(有一個3和更簡單的方式爲好,這是我現在忘了..)

+0

感謝@nos ...這是我的一個基本疏忽,沒有正確寫出分組查詢,但問題不同。我編輯它...你能再次檢查嗎? :) – fenderplayer 2009-08-04 13:38:32

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。因爲。通過內部聯接,您只能訪問至少有一條評論的帖子。通過左連接,您可以選擇未註釋的帖子。

我希望這會有所幫助。

+0

我無法訪問$ this-> posts中的'numofcomments'。這種方法可能需要定製保溼方法。我不知道該怎麼做。 – fenderplayer 2009-08-05 13:47:22

1

如果要打包自定義查詢返回的對象中的其他數據,可以覆蓋對等類中的默認doSelect()方法,並將查詢中的這些附加數據添加到每個對象中這是返回。

在你的posts類中,你可以添加一個保護變量,我們稱之爲「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; 
}