2011-07-09 58 views
45

我想從特定項目的所有訂單中選擇訂單項目。在SQL我會這樣做︰做一個WHERE ..在學說2中的子查詢中

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 

我將如何做查詢生成器這個查詢?

回答

71

這是我怎麼會嘗試:

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

我沒有測試,當然這一點,並提出對您的模型的一些假設。可能的問題:

  • 限制:在Doctrine 2中這有些問題,它似乎查詢生成器不太擅長接受限制。看看here,herehere
  • IN子句通常與數組一起使用,但我認爲它可以與子查詢一起使用。
  • 你可能可以使用相同的參數?1,而不是兩個參數(因爲它們是相同的值),但我不確定。

總結,這可能不是第一次,但肯定會把你放在正確的軌道上。事後告訴我們最終的100%正確答案。

+4

謝謝!在你的例子中只有兩樣東西缺失:命名空間在開始時需要一個反斜槓,並且子查詢需要用getDQL()方法作爲字符串給出。我編輯了您的示例以更正此問題 – chiborg

+5

感謝您的更正。對於使用Doctrine 2 QueryBuilder的人來說,這將是一個非常有用的參考。最好的問候 – faken

+1

這個解決方案似乎不適用於Doctrine2.0。 Doctrine \ ORM \ Query \ Expr-> in()將第二個參數轉換爲數組。如果你通過DQL,它不會被解釋。 – clang1234

5

只是爲了避免混淆clang1234發佈的最後一條評論。

dql查詢示例真正起作用。確實,expr-> in()會將第二個參數強制轉換爲數組,在本例中爲dql字符串。它所做的只是創建一個包含dql查詢字符串的數組作爲第一個元素。這正是Expr \ Func正在等待的一個數組。在Doctrine 2代碼中,dql查詢字符串數組元素將得到正確管理。 (有關更多詳細信息,請參閱DBAL/Platforms/AbstractPlatform.php方法getInExpression獲取更多詳細信息,數組將被內插入IN())