CakePHP 3-如何为同一个字段定义多个条件?
我正在使用CakePHP3.5.13开发一个应用程序。它被绑定到一个“遗留”数据库,即一个没有按照CakePHP命名约定编写的数据库。尽管如此,我还是烘焙了它并生成了表和实体文件 我在使用ORM构造SQL查询时遇到问题 在纯SQL中,查询如下所示:CakePHP 3-如何为同一个字段定义多个条件?,cakephp,query-builder,cakephp-3.x,Cakephp,Query Builder,Cakephp 3.x,我正在使用CakePHP3.5.13开发一个应用程序。它被绑定到一个“遗留”数据库,即一个没有按照CakePHP命名约定编写的数据库。尽管如此,我还是烘焙了它并生成了表和实体文件 我在使用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 (14
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());
上面的查询工作正常,但不完整:它将给出所有结果,但不考虑(在普通SQL中)包含(147)中的fs.filter\u id的行
我遇到的问题是,我不知道如何生成多个和子查询
我尝试了以下几点:
// 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错误
请告知是否/如何在ORM中构造此查询
我曾考虑过采用“原始SQL”的手工编写方法。这似乎是一个巨大的耻辱,因为ORM正在做我需要的95%
我读过这本书,这是我如何设法完成工作的第一部分。然而,该示例中的查询可以说不那么复杂,并且不能满足我在这里的需要
重要:原始SQL生成正确的结果。我知道有些人可能会说,为什么不将
ID中的所有组合到一个查询中呢。然而,这将产生非常不同的——而且是不正确的——结果。中的。。。而在这里
是非常重要的。我知道查询很好,我感兴趣的是如何在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
])
另见
我理解,如果组中可能出现相同的物质id
,则不能将中的和中的组合在一起,但是中的前两个应该是可合并的,因为它们是通过和?@ndm组合在一起的。如果您尝试这样做,将会产生非常不同的结果。这就是我添加“重要”注释的原因。例如,如果我在原始SQL中执行,其中fs.filter_id在(147,47,93))
(全部在一个条件下),它将生成6000多行。然而,当它们分开时,它产生2(fs.filter\u id在(147)
中,然后是fs.filter\u id在(47,93)
)。不幸的是,我不能提供数据库。但是以这种方式运行查询时会有一些细微的差别。是的,对不起,我有点分心,当然这是不同的,因为中的基本上是或的列表……没问题,我总是很感谢任何帮助。我想我的问题是,这样的条件是否可以在ORM中编写,或者我是否最好走“在蛋糕中编写您自己的SQL”的道路?这是一个遗憾,因为ORM使编写大部分查询变得非常简单,我不想编写构造SQL所有这些部分的东西。这个应用程序允许用户选择不同的过滤器,所以也有不同的选择,但现在我最感兴趣的是知道这是否可以通过ORM实现。这真的很好。用于构造此类语句的普通PHP要复杂得多。我很高兴ORM能够做到这一点。