2009-08-03 15 views
1

ブログ投稿のリストを持つページに各ブログ投稿のコメント数(カテゴリ、日付、著者など)を表示します。どのようにpropelに次のmysqlクエリを書くのですか?Propelを使用したSqlクエリ(inner join + count + group by)

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_idとのコメントのテーブルです。私は結果セットの列として 'numofcomments'を取得することはできません。

$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」にアクセスできます。現在、私は(私の最後の手段となります)非ORMのアプローチを使用していますか?

EDIT:私が知りたかったのは、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); 

次にテンプレートで、私のようにアレイにアクセス:

私はテンプレートに「post_array [ 『タイトル』]」書くことができるように、私はモデルの配列の関連付けを行うにはどうすればよい
<div id="title"> 
    <?php echo post_array[1] ?> 
</div> 
//...and so on for other Post fields 

の代わりに " 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

0

ここでは、SQLクエリのPropelのバージョンです。

$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」を使用する必要があります。なぜなら。内部結合では、少なくとも1つのコメントを持つ投稿にのみアクセスできます。左結合では、コメントのない投稿を選択できます。

こちらがお役に立てば幸いです。

+0

$ this-> postsの 'numofcomments'にアクセスできません。このアプローチはおそらくカスタム水和法を必要とする。私はそれを行う方法がわかりません。 – fenderplayer

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; 
} 
関連する問題