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
])
另见
我正在使用 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
])
另见