【问题标题】:Doing a WHERE .. IN subquery in Doctrine 2在 Doctrine 2 中执行 WHERE .. IN 子查询
【发布时间】: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

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

【问题讨论】:

    标签: sql database doctrine-orm


    【解决方案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 中有点问题,似乎查询生成器不太擅长接受限制。看看hereherehere
    • 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()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-27
      • 2014-09-23
      • 1970-01-01
      • 1970-01-01
      • 2015-10-04
      • 2021-01-28
      • 1970-01-01
      相关资源
      最近更新 更多