Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Doing a WHERE .. IN subquery in Doctrine 2

I'd like to select order items from all orders with a specific item. In SQL I'd do it like this:

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 

How would I do this query with the query builder?

like image 921
chiborg Avatar asked Jul 09 '11 21:07

chiborg


People also ask

Can you use WHERE in a subquery?

You can place the Subquery in a number of SQL clauses: WHERE clause, HAVING clause, FROM clause. Subqueries can be used with SELECT, UPDATE, INSERT, DELETE statements along with expression operator.

Is subquery allowed in WHERE clause in MySQL?

In MySQL, a subquery is a query within a query. You can create subqueries within your SQL statements. These subqueries can reside in the WHERE clause, the FROM clause, or the SELECT clause.

Why would you use a subquery in a having or WHERE clause?

Subqueries in a HAVING clause HAVING clause is used to filter groups of rows. You may place a subquery in HAVING clause in an outer query. This allows you to filter groups of rows based on the result returned by your subquery.


2 Answers

This is how I would try it:

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

I didn't test this of course, and made some assumptions about your models. Possible problems:

  • Limit: this has been somewhat of a problem in Doctrine 2, it seems query builder is not very good at accepting limits. Do take a look here, here and here.
  • The IN clause is usually used with an array, but I think it will work with a subquery.
  • You probably can use the same parameter ?1, instead of two parameters (because they're the same value), but I'm not sure.

Concluding, this may not work first time, but will surely put you on the right track. Do tell us the final 100% correct answer afterwards.

like image 118
faken Avatar answered Oct 09 '22 03:10

faken


Just to avoid confusion of the last comment posted by clang1234.

The DQL query example really works. It's true that the The expr->in() will cast the second parameter to an array, in this case the DQL string. What it does, it just create an array with the DQL query string as the first element. That's exactly what the the Expr\Func is waiting for, an array. It's a little deeper in the Doctrine 2 code that the dql query string array element will be managed correctly. (see DBAL/Platforms/AbstractPlatform.php method getInExpression for more details, the array get imploded into IN())

like image 35
user1370289 Avatar answered Oct 09 '22 02:10

user1370289