我正在使用CakePHP 3.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 (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错误。
请问是否有人可以建议在ORM中构建此查询是否可行?如何?
我考虑过去"原始SQL"手写的路线。这似乎是一个很大的耻辱,因为ORM正在做我需要的95%。
我已阅读Cakephp 3 NOT IN query,这就是我如何设法完成工作所需的第一部分。但是,该示例中的查询可能不那么复杂,并且不能满足我的需求。
重要:原始SQL会生成正确的结果。我知道有些人可能会说,为什么不将所有IN
ID分组到一个查询中。但是,这会产生非常不同 - 而且不正确 - 的结果。 IN... AND IN
在这里非常重要。我知道查询很好,它是如何在Cake的我感兴趣的ORM中编写的。
答案 0 :(得分:3)
您的问题基本上是您需要多次使用相同的标识符,这在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
])
另见