【发布时间】:2018-03-21 16:02:42
【问题描述】:
我正在使用 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怎么写。
【问题讨论】:
-
我知道您不能组合
IN和NOT IN以防相同的substance_id可能出现在组中,但前两个IN应该是可合并的,因为它们通过AND? 组合在一起? -
@ndm 如果您尝试这样做,它会给出非常不同的结果。这就是我添加“重要”注释的原因。例如,如果我执行 - 在原始 SQL 中 -
WHERE fs.filter_id IN (147,47,93))(全部在一个条件下)它会产生超过 6000 行。而当它们分开时它会产生 2(fs.filter_id IN (147)后跟fs.filter_id IN (47,93))。不幸的是,我无法提供数据库。但是以这种方式运行查询时存在细微差别。 -
是的,对不起,我有点分心了,当然不一样,因为
IN基本上是OR的列表... -
没问题,我总是感谢任何帮助。我想我的问题是这样的条件是否可以写在 ORM 中,或者我是否最好走“在 Cake 中编写自己的 SQL”这条路?这是一种耻辱,因为 ORM 使编写大部分查询变得非常容易,而且我讨厌必须编写一些东西来构造 SQL 的所有这些部分。该应用程序允许用户选择各种过滤器,因此也有不同的过滤器,但现在我最感兴趣的是知道这是否可以通过 ORM 实现。
标签: cakephp query-builder cakephp-3.x