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

我想从带有特定商品的所有订单中选择订单商品。 在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

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

chiborg asked 2019-11-14T22:35:18Z
2个解决方案
101 votes

这是我会尝试的方式:

/** @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)
   ;

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

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

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

faken answered 2019-11-14T22:36:22Z
9 votes

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

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

user1370289 answered 2019-11-14T22:36:53Z
translate from https://stackoverflow.com:/questions/6637506/doing-a-where-in-subquery-in-doctrine-2