我想查询“ Articles”,但我只希望“ Articles”具有两个或更多“ Comments”。因此,我必须计算“注释”,并在where子句中使用计数结果。
我知道下一个代码是错误的,但它类似于:
$articles = $this->Articles->find();
$articles->matching('Comments', function ($q) {
$commentsCount = $q->func()->count('Comments.id');
return $q->where($commentsCount . ' >= ' => 2);
});
我找不到有关此的任何信息。
感谢您的帮助。
它总是有助于首先弄清楚如何在原始SQL中进行操作,这将使它更容易确定如何使用CakePHP的查询构建器进行复制。
例如,您不能在WHERE
子句中使用聚合,所有支持的DBMS都禁止使用该聚合。 WHERE
的评估是在应用[[before分组之前(即,在没有任何计数之前),您必须在HAVING
子句中检查聚合,该子集的评估是after分组。
SELECT
Articles.id, ...
FROM
articles Articles
LEFT JOIN
comments Comments ON Comments.article_id = Articles.id
GROUP BY
Articles.id
HAVING
COUNT(Comments.id) >= 2
这可以通过这样的查询构建器轻松实现:
$query = $this->Articles ->find() ->leftJoinWith('Comments') ->group('Articles.id') ->having(function ( \Cake\Database\Expression\QueryExpression $exp, \Cake\ORM\Query $query ) { return $exp->gte( $query->func()->count('Comments.id'), 2, 'integer' ); });
这样的查询在大型表上可能非常昂贵,因为它不能使用任何索引,因此需要全表扫描,即,它必须检查每一行。避免这种情况的一种方法是使用计数器缓存,该缓存将源表中关联记录的数量存储在该表中,您可以将其与Articles
表中的可索引列进行比较,即可以执行以下操作:
$query = $this->Articles ->find() ->where([ 'Articles.comment_count >=' => 2, ]);
另请参见