通过计数关联数据过滤查询Cakephp 3

问题描述 投票:0回答:1

我想查询“ Articles”,但我只希望“ Articles”具有两个或更多“ Comments”。因此,我必须计算“注释”,并在where子句中使用计数结果。

我知道下一个代码是错误的,但它类似于:

$articles = $this->Articles->find();

$articles->matching('Comments', function ($q) {
    $commentsCount = $q->func()->count('Comments.id');   
    return $q->where($commentsCount . ' >= ' => 2);
});

我找不到有关此的任何信息。

感谢您的帮助。

cakephp query-builder counting cakephp-3.x aggregates
1个回答
0
投票

它总是有助于首先弄清楚如何在原始SQL中进行操作,这将使它更容易确定如何使用CakePHP的查询构建器进行复制。

例如,您不能在WHERE子句中使用聚合,所有支持的DBMS都禁止使用该聚合。 WHERE的评估是在应用[[before分组之前(即,在没有任何计数之前),您必须在HAVING子句中检查聚合,该子集的评估是after分组。

通常,您将按照SQL的方式进行一些操作:

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, ]);

另请参见

© www.soinside.com 2019 - 2024. All rights reserved.