2012-08-12 4 views
20

Desidero selezionare membri che non sono in servizio specifico. Ho 3 tabelle:Sottoquery in doctrine2 notIN Funzione

  • membre
  • service
  • membre_service (rapporto tra membre e service)

sto usando la dottrina 2 e in SQL la mia domanda è:

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

In 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(); 

ho ottenuto il seguente errore:

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

risposta

35

lo stesso alias non può essere definito 2 volte nella stessa query

$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(); 

Idealmente si dovrebbe usare molti-a-molti relazione per la tua entità, in questo caso la tua domanda sarà molto più semplice.

+0

Grazie per la risposta! MembreService è già in molti-a-molti ... Mi hai davvero aiutato! E vedi la mia modifica per la risposta finale. May God Bless You ... –

+0

Se si utilizzano i parametri nella sottoquery: $ qb-> setParameters ($ qb2-> getParameters()); è necessario, sebbene tu possa volere $ qb-> setParameters (array_merge ($ qb2-> getParameters(), $ qb-> getParameters())) per evitare di sovrascrivere i parametri dalla query esterna. – Omn

+0

Hmmm ... prendi il mio ultimo commento con un pizzico di sale, che sembra funzionare solo in alcune versioni della dottrina ... in altre versioni setParameters sostituisce piuttosto che aggiunge ai parametri ... – Omn

11

In realtà se si utilizza la classe repository Symfony2 si potrebbe anche effettuare le seguenti operazioni:

$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

Grazie per questo. Stavo cercando un modo per farlo con diversi repository, la tua soluzione ha fatto il trucco. – mason81

+0

In '$ q-> expr()', che cos'è '$ q'? – psylosss

+1

$ q è un'istanza di QueryBuilder. Il codice corretto sarebbe il seguente: '' '$ q = $ this-> createQueryBuilder ('m'); $ Q-> dove ($ q-> expr() -> notIn() ....)) '' ' – versedi

4

È possibile utilizzare (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(); 

Vedere la documentation per ulteriori esempi.