CakePHP 3 - 如何为同一个字段定义多个条件?

CakePHP 3 - How to define multiple conditions for one and the same field?

我正在使用 CakePHP 3.5.13 开发一个应用程序。它与 "legacy" 数据库相关联 - 即未根据 CakePHP 命名约定编写的数据库。尽管如此,我还是对其进行了烘焙并生成了 Table 和实体文件。

我在使用 ORM 构建 SQL 查询时遇到问题。

查询 - 简单来说 SQL - 看起来像这样:

SELECT s.id FROM substances s WHERE s.id 
IN
    (SELECT fs.substance_id FROM filters_substances fs WHERE fs.filter_id IN (147))
AND s.id IN 
    (SELECT fs.substance_id FROM filters_substances fs WHERE fs.filter_id IN (47,93))
AND s.id NOT IN
    (SELECT fs.substance_id FROM filters_substances fs WHERE fs.filter_id IN (148,354))

我已经使用 ORM 编写了以下内容:

$subquery_in = $FiltersSubstances
    ->find()
    ->select(['FiltersSubstances.substance_id'])
    ->where(['FiltersSubstances.filter_id IN' => [47,93]]);

$subquery_not_in = $FiltersSubstances
    ->find()
    ->select(['FiltersSubstances.substance_id'])
    ->where(['FiltersSubstances.filter_id IN' => [354]]);

$Substances = TableRegistry::get('Substances');

$query = $Substances
    ->find()
    ->where([
        'Substances.id IN' => $subquery_in,
        'Substances.id NOT IN ' => $subquery_not_in
    ]);

debug($query);
debug($query->all());

上面的查询工作正常但不完整:它会给我所有结果但没有考虑包含 fs.filter_id IN (147) 的行(在普通 SQL 中)。

我遇到的问题是我不知道如何生成多个 AND IN 子查询。

我尝试了以下操作:

// Same as PHP given previously, plus:

$subquery_in2 = $FiltersSubstances
    ->find()
    ->select(['FiltersSubstances.substance_id'])
    ->where(['FiltersSubstances.filter_id IN' => [147]]);

// Modified $query:

$query = $Substances
    ->find()
    ->where([
        'Substances.id IN' => [$subquery_in, $subquery_in2],
        'Substances.id NOT IN ' => $subquery_not_in]
    );

// Also tried:

$query = $Substances
    ->find()
    ->where([
        'Substances.id IN' => $subquery_in,
        'Substances.id IN' => $subquery_in2,
        'Substances.id NOT IN ' => $subquery_not_in
    ]);

以上尝试无效 - SQL 个错误。

任何人都可以建议 if/how 可以在 ORM 中构造此查询吗?

我考虑过 "raw SQL" 手写的路线。这看起来很遗憾,因为 ORM 完成了我需要的 95%。

我已阅读 这就是我如何设法完成我需要完成的工作的第一部分。然而,该示例中的查询可以说不那么复杂,不符合我的需求。

重要提示:原始 SQL 会产生正确的结果。我知道有些人可能会说,为什么不将所有 IN ID 组合到一个查询中。但是,这会产生非常不同且不正确的结果。 IN... AND IN 在这里非常重要。我知道查询没问题,我感兴趣的是如何在Cake的ORM中编写它。

你的问题基本上是你需要多次使用相同的标识符,这在 PHP 数组中是无效的。

您可以通过嵌套条件来解决此问题:

->where([
    ['Substances.id IN' => $subquery_in],
    ['Substances.id IN' => $subquery_in2],
    'Substances.id NOT IN ' => $subquery_not_in
])

通过发出多个 where() 调用:

->where(['Substances.id IN' => $subquery_in])
->where(['Substances.id IN' => $subquery_in2])
->where(['Substances.id NOT IN' => $subquery_not_in])

或使用表达式:

->where(function (\Cake\Database\Expression\QueryExpression $exp) use (
    $subquery_in,
    $subquery_in2,
    $subquery_not_in
) {
    return $exp
        ->in('Substances.id', $subquery_in)
        ->in('Substances.id', $subquery_in2)
        ->notIn('Substances.id', $subquery_not_in);
})

也可以将表达式与常规数组语法混合使用:

$inExpressions = $query
    ->newExpr()
    ->in('Substances.id', $subquery_in)
    ->in('Substances.id', $subquery_in2);

// ...

->where([
    $inExpressions,
    'Substances.id NOT IN ' => $subquery_not_in
])

另见