在一对多情况下具有 ID 数组的查询构建器

Posted

技术标签:

【中文标题】在一对多情况下具有 ID 数组的查询构建器【英文标题】:Querybuilder with array of Id's in a one to many situation 【发布时间】:2021-08-16 15:54:39 【问题描述】:

我正在使用 Symfony 3.4 及其学说查询构建器。我有一个实体广告,它在一个太多的关系中有不同的选项。因此,我正在构建一个过滤器。

$optionIds 是一个数组,有多个整数表示 option.id

我有以下过滤器:

            $query->leftJoin('ad.options', 'opt')
            ->andWhere($query->expr()->in('opt.id', ':optionIds'))
            ->setParameter('optionIds', $optionIds)

此过滤器的问题在于它返回所有链接了其中一个选项的广告。想法是只获取所有 id 链接的广告。所以这个过滤器是一个 OR 而不是一个 AND 过滤器?

第二个问题是,如果它匹配多个选项 ID,它会多次返回同一个广告。我不想使用 groupBy 来解决这个问题。

我还将代码更改为以下内容:

         $cnt = 0;
        foreach ($optionIds as $optionId) 
            $query->leftJoin('ad.options', 'opt'.$cnt)
                ->andWhere('opt'.$cnt.'.id = :id'.$cnt)
                ->setParameter('id'.$cnt++, $optionId);
        

这可行,但速度很慢。

感谢帮助,我已经半天了!

【问题讨论】:

【参考方案1】:

要检查广告是否应该存在所有选项,您需要使用聚合并过滤聚合结果

$query->addSelect('COUNT(DISTINCT opt.id) AS total_options')(
      ->leftJoin('ad.options', 'opt')
      ->andWhere($query->expr()->in('opt.id', ':optionIds'))
      ->addGroupBy('ad.id')
      ->having('total_options = '.count($optionIds))
      ->setParameter('optionIds', $optionIds)

有关参考和更多详细信息,请参阅我对多对多关系中类似情况的其他答案

Symfony2 - Doctrine2 QueryBuilder WHERE IN ManyToMany field

Sql/Doctrine query to find data with multiple condition with Many to Many associations

【讨论】:

是否有不返回 total_options 值的选项?那么计数器值仅在查询中使用吗? @Tom 您可以在查询生成器中使用HIDDEN 关键字来将列从结果集中隐藏为COUNT(DISTINCT opt.id) AS HIDDEN total_options 是否可以在 ->andWhere($query->expr()->in('opt.id', ':optionIds')) 中添加额外的条件?我喜欢添加不仅要匹配 opt.id,还要添加同一实体中其他字段的最小值和最大值。 @Tom 如果您可以提出一个包含所有相关详细信息的新问题以便其他用户了解,那就太好了

以上是关于在一对多情况下具有 ID 数组的查询构建器的主要内容,如果未能解决你的问题,请参考以下文章

具有一对多关系的灵活查询

Excel一对多查询(index+small+if)

MyBatis高级篇 - 关联查询(一对一)

一对多关系在不使用“distinct”的情况下获取重复的对象。为啥?

具有一对多关系的 GraphQL 循环查询

MyBatis高级篇 - 关联查询(一对多)