在 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 子查询的主要内容,如果未能解决你的问题,请参考以下文章
有人可以建议一种使用带有多个“where”子句的 Doctrine (QueryBuilder) 进行此查询的方法吗?
如何在 Doctrine 中使用 WHERE 作为 JOINed 表的外键?
如何在 Doctrine 查询生成器中进行多个 WHERE IN 列查询?