在 Doctrine 2 中执行 WHERE .. IN 子查询

Posted

技术标签:

【中文标题】在 Doctrine 2 中执行 WHERE .. IN 子查询【英文标题】:Doing a WHERE .. IN subquery in Doctrine 2 【发布时间】:2011-10-02 00:34:48 【问题描述】:

我想从所有带有特定商品的订单中选择订单商品。在 SQL 中,我会这样做:

SELECT DISTINCT i.id, i.name, order.name 
FROM items i 
JOIN orders o ON i.order_id=o.id 
WHERE o.id IN (
   SELECT o2.id FROM orders o2
   JOIN items i2 ON i2.order_id=o2.id AND i2.id=5
)
AND i.id != 5
ORDER BY o.orderdate DESC
LIMIT 10

如何使用查询生成器进行此查询?

【问题讨论】:

【参考方案1】:

我会这样尝试:

/** @var Doctrine\ORM\EntityManager $em */
$expr = $em->getExpressionBuilder();
$em->createQueryBuilder()
   ->select(array('DISTINCT i.id', 'i.name', 'o.name'))
   ->from('Item', 'i')
   ->join('i.order', 'o')
   ->where(
       $expr->in(
           'o.id',
           $em->createQueryBuilder()
               ->select('o2.id')
               ->from('Order', 'o2')
               ->join('Item', 
                      'i2', 
                      \Doctrine\ORM\Query\Expr\Join::WITH, 
                      $expr->andX(
                          $expr->eq('i2.order', 'o2'),
                          $expr->eq('i2.id', '?1')
                      )
               )
               ->getDQL()
       )
   )
   ->andWhere($expr->neq('i.id', '?2'))
   ->orderBy('o.orderdate', 'DESC')
   ->setParameter(1, 5)
   ->setParameter(2, 5)
   ;

我当然没有对此进行测试,并对您的模型做了一些假设。可能的问题:

限制:这在 Doctrine 2 中有点问题,似乎查询生成器不太擅长接受限制。看看here、here 和here。 IN 子句通常与数组一起使用,但我认为它可以与子查询一起使用。 您可能可以使用相同的参数 ?1,而不是两个参数(因为它们是相同的值),但我不确定。

最后,这可能不会第一次奏效,但肯定会让你走上正轨。之后请告诉我们最终的 100% 正确答案。

【讨论】:

谢谢!您的示例中只缺少两件事:命名空间在开头需要一个反斜杠,子查询需要使用 getDQL() 方法作为字符串给出。我已编辑您的示例以更正此问题 感谢您的更正。对于使用 Doctrine 2 QueryBuilder 的每个人来说,这将是一个非常有用的参考。最好的问候 这个解决方案似乎在 Doctrine2.0 中不起作用。 Doctrine\ORM\Query\Expr->in() 将第二个参数转换为数组。如果传入 DQL,则不会被解释。 如果内部查询有一些绑定参数,这可能很危险,因为根据我的经验调用 getDql() 会使任何此类绑定无效。因此,需要在外部查询中再次将参数与 setParameter 绑定,否则代码会出现“无效的参数编号:绑定变量的数量与标记的数量不匹配”。 请注意,示例中使用了两个查询构建器。这应该可以为下一个人节省一些时间......【参考方案2】:

只是为了避免混淆 clang1234 发布的最后一条评论。

DQL 查询示例确实有效。确实,expr->in() 会将第二个参数转换为数组,在本例中为 DQL 字符串。它的作用是创建一个以 DQL 查询字符串作为第一个元素的数组。这正是 Expr\Func 正在等待的,一个数组。将正确管理 dql 查询字符串数组元素在 Doctrine 2 代码中更深入一点。 (有关更多详细信息,请参阅DBAL/Platforms/AbstractPlatform.php 方法 getInExpression,数组被内爆到 IN()

【讨论】:

以上是关于在 Doctrine 2 中执行 WHERE .. IN 子查询的主要内容,如果未能解决你的问题,请参考以下文章

Doctrine 2 WHERE IN 子句使用实体集合

有人可以建议一种使用带有多个“where”子句的 Doctrine (QueryBuilder) 进行此查询的方法吗?

如何在 Doctrine 中使用 WHERE 作为 JOINed 表的外键?

如何在 Doctrine 查询生成器中进行多个 WHERE IN 列查询?

Doctrine2 查询(Builder)在使用“where”和“in”子句后失去关系

如何在 Doctrine 中使用 andWhere 和 orWhere?