7

I want to implement a subquery using the query builder but I'm not understanding the syntax. I'm dealing with a locations table that has entries that can be cities, states or zip codes depending on the location type set. I want to get all locations that are in a certain state and take out any that are city type and have a population below a certain amount.

$qb->select('l')
->from('Entity\Location', 'l')
->where('l.state = :state')
->setParameter('state', 'UT')
->andWhere('...don't know what to put here');

In the andWhere I basically need to say

and where id not in (select id from location where location_type = 1 and population < 1000)

Update: I was able to do this with straight DQL but it would be nice to see how to do it using the query builder.

$qb->andWhere('l.id NOT IN (SELECT l2.id FROM Entity\Location AS l2 WHERE l2.location_type = 1 AND l2.population < 1000)');
Jeremy Hicks
  • 3,690
  • 5
  • 40
  • 52
  • Looks like I don't even need a subquery actually. However, Guilherme also suggested that I can just use a second query builder instance and use that as the second argument of an in expression. http://groups.google.com/group/doctrine-user/browse_thread/thread/f72c104fe334f87c – Jeremy Hicks May 10 '11 at 20:09

1 Answers1

4

In the documentation of Doctrine I found this:

// Example - $qb->expr()->in('u.id', array(1, 2, 3))
// Make sure that you do NOT use something similar to $qb->expr()->in('value', array('stringvalue')) as this will cause Doctrine to throw an Exception.
// Instead, use $qb->expr()->in('value', array('?1')) and bind your parameter to ?1 (see section above)
public function in($x, $y); // Returns Expr\Func instance

// Example - $qb->expr()->notIn('u.id', '2')
public function notIn($x, $y); // Returns Expr\Func instance

It should be possible to put a subquery in this function. I never used it myself, but according to the documentation it should look like this.

$qb->select('l')
   ->from('Entity\Location', 'l')
   ->where('l.state = :state')
   ->setParameter('state', 'UT')
   ->andWhere($qb->expr()->notIn('u.id', 
       $qb->select('l2.id')
          ->from('Entity\Location', 'l2')
          ->where(l2.location_type = ?1 AND l2.population < ?2)
          ->setParameters(array(1=> 1, 2 => 1000))
));

I'm not 100% sure the example above is correct, but give it a try.

Rene Terstegen
  • 7,911
  • 18
  • 52
  • 74
  • I know this is really old, but for someone coming across this from a search engine (like me), here's how I got this to work: `in()` or `notIn()` expressions don't support a QueryBuilder instance passed to them, but they support a DQL string. For that you just need to add `->getDQL()` at the end of the sub-query code. Also, pay attention that you need to use a separate QueryBuilder for the sub-query and can't reuse the same `$qb` instance as seen here. Otherwise it does indeed work this way. – Dennis98 Mar 14 '22 at 14:51