web-dev-qa-db-fra.com

Sous-requête dans la fonction doctrineIN2 notIN

J'aimerais sélectionner des membres qui ne sont pas dans un service spécifique. J'ai 3 tables:

  • membre
  • service
  • membre_service (relation entre membre et service)

J'utilise doctrine 2 et en SQL ma requête est:

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

Dans Doctrine, je fais:

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

J'ai eu l'erreur suivante:

Erreur sémantique] ligne 0, col 123 près de 'm WHERE ms.id': Erreur: 'm' est déjà défini.

23
Marcel Djaman

Le même alias ne peut pas être défini 2 fois dans la même requête

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

Idéalement, vous devriez utiliser une relation plusieurs-à-plusieurs pour votre entité, dans ce cas, votre requête sera beaucoup plus simple.

45
WizardZ

En fait, si vous utilisez la classe de référentiel Symfony2, vous pouvez également effectuer les opérations suivantes:

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

Vous pouvez utiliser (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();

Voir documentation pour plus d'exemples.

6
Stephan Vierkant