Делая ГДЕ .. В подзапросе в Учении 2 - PullRequest
54 голосов
/ 10 июля 2011

Я бы хотел выбрать элементы заказа из всех заказов с определенным элементом.В 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

Как бы я сделал этот запрос с помощью построителя запросов?

Ответы [ 2 ]

95 голосов
/ 10 июля 2011

Вот как я бы это попробовал:

/** @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, кажется, что построитель запросов не очень хорош в принятии ограничений.Посмотрите здесь , здесь и здесь .
  • Предложение IN обычно используется с массивом, но я думаю, что оно будет работатьс подзапросом.
  • Возможно, вы можете использовать один и тот же параметр? 1 вместо двух параметров (потому что они имеют одинаковое значение), но я не уверен.

В заключение, это может не сработать в первый раз, но, несомненно, поставит вас на правильный путь.Сообщите нам окончательный 100% правильный ответ.

9 голосов
/ 02 мая 2012

Просто, чтобы избежать путаницы с последним комментарием, опубликованным clang1234.

пример запроса dql действительно работает. Это правда, что expr-> in () приведёт второй параметр к массиву, в данном случае строку dql. Что он делает, он просто создает массив со строкой запроса dql в качестве первого элемента. Это именно то, что ожидает Expr \ Func, массив. В коде Doctrine 2 немного глубже, что элемент массива строки запроса dql будет управляться правильно. (см. DBAL / Platforms / AbstractPlatform.php метод getInExpression для более подробной информации, массив вставляется в IN ())

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...