CakePHP 4:如何将关联结果的计数添加到 where 条件

问题描述

我正在尝试将关联的计数结果添加到 where 条件中,例如:

$findQuery = $this->Products->find('all');

$findQuery->leftJoinWith('Synonyms',function($q) {
    return $q->where(['Synonyms.title LIKE' => '%TEST%']);
});
$findQuery->select([
    'amount_of_matching_synonyms' => $findQuery->func()->count('Synonyms.id')
]);
$findQuery->where([
    'OR' => [
        'Products.description LIKE' => '%TEST%','amount_of_matching_synonyms >' => 0
    ]
]);

现在发生的是,我得到了 1 个结果,其中包含 'amount_of_matching_synonyms' 字段。但这似乎有它应该返回的所有记录的累积结果。

请帮帮我!

解决方法

您应该首先弄清楚如何在纯 SQL 中执行这些操作,然后将内容转换到查询构建器中会容易得多。

计算相关数据需要加入相关数据并创建可以使用聚合函数的组,而您错过了后者。此外,您不能在 WHERE 子句中使用聚合,因为在应用 WHERE 子句之后进行分组,因此您必须改用 HAVING 子句。

用于过滤此类计数的基本 SQL 如下所示:

SELECT
    COUNT(synonyms.id) amount_of_matching_synonyms
FROM
    products
LEFT JOIN
    synonyms ON synonyms.id = synonyms.product_id
GROUP BY
    products.id
HAVING
    amount_of_matching_synonyms > 0

将其转换为查询构建器将相当简单,您只需要 group()having(),如下所示:

$findQuery = $this->Products
    ->find()
    ->select([
        'Products.description','amount_of_matching_synonyms' => $findQuery->func()->count('Synonyms.id')
    ])
    ->leftJoinWith('Synonyms',function(\Cake\ORM\Query $q) {
        return $q->where(['Synonyms.title LIKE' => '%TEST%']);
    })
    ->group('Products.id')
    ->having([
        'OR' => [
            'Products.description LIKE' => '%TEST%','amount_of_matching_synonyms >' => 0
        ],]);

注意一定要选择描述,否则have子句中的条件会失败。

生成的 SQL 看起来像这样:

SELECT
    products.description,COUNT(synonyms.id) amount_of_matching_synonyms
FROM
    products
LEFT JOIN
    synonyms ON
        synonyms.product_id = products.id
        AND
        synonyms.title LIKE '%TEST%'
GROUP BY
    products.id
HAVING
    products.description LIKE '%TEST%'
    OR
    amount_of_matching_synonyms > 0

另见

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...