4

I have a Comments table that have parent_id foreign key that points to itself to enable threaded comment.

Comments
id INT UNSIGNED NOT NULL
parent_id INT UNSIGNED NULL
comment TEXT NOT NULL
created_time DATETIME NOT NULL

The original ActiveQuery is like this

class CommentActiveQuery extends \yii\db\ActiveQuery {
    public function andWhereIsNotRemoved() {
        return $this->andWhere(['isRemoved' => Comment::STATUS_IS_NOT_REMOVED]);
    }

    public function andWhereParentIdIs($parentId) {
        return $this->andWhere(['parentId' => $parentId]);
    }

    public function orderByNewestCreatedTime() {
        return $this->orderBy(['createdTime' => SORT_DESC]);
    } 
}

Now I want to sort the comments by the newest active reply.

The query is basically like this

SELECT `*`, `last_reply_time` 
    FROM `Comments` 
    WHERE `parent_id` IS NULL 
    ORDER BY `last_reply_time` DESC;

I'm thinking the last_reply_time is a subquery

SELECT MAX(created_time) 
   FROM `Comments` 
   WHERE `parent_id` = :something

How to build this using the CommentActiveQuery above. The farthest I can get is like this

public function orderByNewestActiveChildCreatedTime() {
    return $this->addSelect([
            'last_reply_time' => $subQuery
           ])->orderBy(['last_reply_time' => SORT_DESC]);
} 

With what should I replace the $subQuery variable above? Or is there a better way?

1 Answer 1

1
$subQuery = new \yii\db\Query();
$subQuery->select(["max(subQ.created_time)"]);
$subQuery-> from('comments subQ');
$subQuery->where([
    'parent_id' => $parentId
]);

$query = new \yii\db\Query();
$query->select([
    'C.*',
    $subQuery
]);
$query->from('Comments C');
$query->andWhere(
    'parent_id is Null'
);


$command = $query->createCommand();

 /*

   Printing the command will result following sql  with $parentId = 1     

   SELECT
        `C`.*, (
         SELECT
            max(subQ.created_time)
         FROM
            `comments` `subQ`
         WHERE
             `parent_id` =: qp0
         ) AS `1`
    FROM
         `Comments` `C`
    WHERE
         parent_id IS NULL

*/

print_r($command->sql);

I am not sure about ORDER BY last_reply_time DESC; Assuming last_reply_time is db table attribute and is different from the subquery. You can simply add orderBy in the query by doing $query->orderBy('last_reply_time DESC')

I hope this would be helpful to you.Cheers :)

Sign up to request clarification or add additional context in comments.

1 Comment

Unfortunately this is not an answer, because Query and ActiveQuery are different. According to this github.com/yiisoft/yii2/issues/9720 subqueries with ActiveQuery are still impossible.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.