按计数关联数据过滤查询 CakePHP 3
Filter query by count associated data CakePHP 3
我想查询“文章”,但我只想要有两个或更多“评论”的“文章”。所以我必须对“评论”进行计数,并在 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
在 应用 分组之前被评估(即在可以计算任何东西之前),你必须改为检查 HAVING
子句中的聚合,这是在 分组后评估 。
通常你会按照 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'
);
});
这样的查询在大型 table 上可能非常昂贵,因为它不能使用任何索引,因此需要完整的 table 扫描,即它必须检查每一行。避免这种情况的一种方法是使用计数器缓存,它将关联记录的数量存储在源 table 中,这样您就可以与 Articles
table 中的可索引列进行比较,即然后可以简单地做:
$query = $this->Articles
->find()
->where([
'Articles.comment_count >=' => 2,
]);
另见
我想查询“文章”,但我只想要有两个或更多“评论”的“文章”。所以我必须对“评论”进行计数,并在 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
在 应用 分组之前被评估(即在可以计算任何东西之前),你必须改为检查 HAVING
子句中的聚合,这是在 分组后评估 。
通常你会按照 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'
);
});
这样的查询在大型 table 上可能非常昂贵,因为它不能使用任何索引,因此需要完整的 table 扫描,即它必须检查每一行。避免这种情况的一种方法是使用计数器缓存,它将关联记录的数量存储在源 table 中,这样您就可以与 Articles
table 中的可索引列进行比较,即然后可以简单地做:
$query = $this->Articles
->find()
->where([
'Articles.comment_count >=' => 2,
]);
另见