2012-08-12 14 views
20

Me gustaría seleccionar miembros que no estén en un servicio específico. Tengo 3 tablas:Subconsultar en doctrine2 notIN Función

  • membre
  • service
  • membre_service (relación entre membre y service)

estoy usando la doctrina 2 y en SQL mi consulta es:

SELECT m.* FROM membre m WHERE m.`id` NOT IN (
    SELECT ms.membre_id FROM membre_service ms WHERE ms.service_id != 29 
) 

En Doctrine, I d o:

$qb = $this->_em->createQueryBuilder(); 
$qb2 = $qb; 
$qb2->select('m.id') 
     ->from('Custom\Entity\MembreService', 'ms') 
     ->leftJoin('ms.membre', 'm') 
     ->where('ms.id != ?1') 
     ->setParameter(1, $service); 

    $qb = $this->_em->createQueryBuilder(); 
    $qb->select('m') 
     ->from('Custom\Entity\Membre', 'm') 
     ->where($qb->expr()->notIn('m.id', $qb2->getDQL()) 
    ); 
    $query = $qb->getQuery(); 
    //$query->useResultCache(true, 1200, __FUNCTION__); 

    return $query->getResult(); 

me dieron el siguiente error:

Semantical Error] line 0, col 123 near 'm WHERE ms.id': Error: 'm' is already defined.

Respuesta

35

El mismo alias no puede definirse 2 veces en la misma consulta

$qb = $this->_em->createQueryBuilder(); 
$qb2 = $qb; 
$qb2->select('m.id') 
    ->from('Custom\Entity\MembreService', 'ms') 
    ->leftJoin('ms.membre', 'm') 
    ->where('ms.id != ?1'); 

$qb = $this->_em->createQueryBuilder(); 
$qb->select('mm') 
    ->from('Custom\Entity\Membre', 'mm') 
    ->where($qb->expr()->notIn('mm.id', $qb2->getDQL()) 
); 
$qb->setParameter(1, $service); 
$query = $qb->getQuery(); 

return $query->getResult(); 

Lo ideal es utilizar muchos-a-muchos relación para su entidad, en este caso su consulta será mucho más simple.

+0

¡Gracias por tu respuesta! MembreService ya está en many-to-many ... ¡Realmente me ayudaste! Y vea mi edición para la respuesta final. Que Dios los bendiga ... –

+0

Si está usando parámetros en la subconsulta: $ qb-> setParameters ($ qb2-> getParameters()); es necesario, aunque es posible que desee $ qb-> setParameters (array_merge ($ qb2-> getParameters(), $ qb-> getParameters())) para evitar la anulación de los parámetros de la consulta exterior. – Omn

+0

Hmmm ... tome mi último comentario con un grano de sal, que solo parece funcionar en algunas versiones de la doctrina ... en otras versiones setParameters reemplaza en lugar de agrega a los parámetros ... – Omn

11

En realidad, si usted está utilizando la clase repositorio de Symfony2 también se puede hacer lo siguiente:

$in = $this->getEntityManager()->getRepository('Custom:MembreService') 
    ->createQueryBuilder('ms') 
    ->select('identity(ms.m)') 
    ->where(ms.id != ?1); 

$q = $this->createQueryBuilder('m') 
    ->where($q->expr()->notIn('m.id', $in->getDQL())) 
    ->setParameter(1, $service); 

return $q->getQuery()->execute(); 
+0

Gracias por esto. Estaba buscando una forma de hacer esto con diferentes repositorios, su solución hizo el truco. – mason81

+0

En '$ q-> expr()', ¿qué es '$ q'? – psylosss

+1

$ q es una instancia de QueryBuilder. El código correcto se vería así: '' '$ q = $ this-> createQueryBuilder ('m'); $ q-> donde ($ q-> expr() -> notIn() ....)) '' ' – versedi

4

Puede utilizar (NOT) MEMBER OF:

<?php 
$query = $em->createQuery('SELECT m.id FROM Custom\Entity\Membre WHERE :service NOT MEMBER OF m.services'); 
$query->setParameter('service', $service); 
$ids = $query->getResult(); 

Véase el documentation para más ejemplos.

Cuestiones relacionadas