Zend Framework 3 + Doctrine – CreateQueryBuilder not in and Relationship
Surgiu a necessidade de criar uma consulta na qual relacionava duas tabelas, pois precisaria das informações contidas nas duas, mas eu gostaria de buscar apenas os registros aos quais não houvessem relação, no caso a tabela que recebe a chave estrangeira não poderia conter o identificador da minha tabela primária, foi então que resolvi da seguinte forma:
$rastreador = $em->createQueryBuilder('a'); $rastreadores = $rastreador->select(array('r', 'rm')) ->from(\MODRastreador\Entity\Rastreador::class, 'r') ->leftJoin(\MODRastreamento\Entity\Rastreamento::class, 'rm', Expr\Join::WITH, 'r.id = rm.idRastreador') //AND rm.dataTransferencia IS NOT NULL ->where('r.ativo = ?1') ->andWhere('r.idEmpresa = ?2') ->andWhere($rastreador->expr()->notIn('r.id', $qr_sub->select('DISTINCT(srm.idRastreador)') ->from(\MODRastreamento\Entity\Rastreamento::class, 'srm') ->where('srm.idEmpresa = ?3') ->getDQL() )) ->orderBy('r.imei', 'ASC') ->setParameter(1, true) ->setParameter(2, $this->getIdentityUser()->getId()) ->setParameter(3, $this->getIdentityUser()->getId()) ->getQuery() ->getScalarResult();
Observe o uso do DISTINCT, se você não utilizar não será possível retornar apenas a chave estrangeira idRastreador, o único campo que aceita retorno único é o id, mas como quero apenas os ids de nossa chave estrangeira precisamos utilizar o DISTINCT.
Para entender melhor em uma consulta SQL ficaria da seguinte forma:
select idRastreador from rastreamento
Também dou a dica de tomar cuidado com o where que utilizar na primeira consulta, já que vai fazer uma subconsulta procure realizar os where’s referentes a segunda tabela dentro da subconsulta.
O comando getScalarResult() é apenas para voltar os resultados em forma de array associativo com o índice das tabelas que eu defini, não tem relação alguma com as operações de relacionamento em de subconsultas.