WHERE … IN query with sub-query in Doctrine queryBuilder or equivalent

穿精又带淫゛_ 提交于 2021-01-28 07:01:34

问题


In my Symfony 4 project I have a User entity and a UserRepository. I'm trying to implement the equivalent of this SQL query in the QueryBuilder(Doctrine 2) or even in DQL.

SELECT * FROM user WHERE account_manager_id IN (SELECT id FROM user WHERE account_manager_id = :managerAdminId AND roles LIKE '%ROLE_MANAGER%')

Or maybe use a different syntax.

I tried different things, but couldn't figure out how to write the WHERE ... IN with the sub-query.

This is all I could come up with, which I don't like because it fires multpiple queries for something I could do with a single one:

    //App\Repository\UserRepository

    public function getPublishersOfManagers($managerAdminId)
    {
        //SELECT * FROM user WHERE account_manager_id IN (SELECT id FROM user WHERE account_manager_id = :managerAdminId AND roles LIKE '%ROLE_MANAGER%')

        $managerIds = $this->createQueryBuilder('u')
                    ->select('u.id')
                    ->where('u.roles LIKE :role')
                    ->setParameter('role' , '%ROLE_MANAGER%')
                    ->andWhere('u.accountManager = :managerAdminId')
                    ->setParameter('managerAdminId' , $managerAdminId)
                    ->getQuery()->getArrayResult();

        $publishers = [];

        foreach ($managerIds as $id) {

            $publishers[] = $this->createQueryBuilder('u')
                    ->select('u')
                    ->where('u.roles LIKE :role')
                    ->setParameter('role' , '%ROLE_PUBLISHER%')
                    ->andWhere('u.accountManager = :managerAdminId')
                    ->setParameter('managerAdminId' , $id)
                    ->getQuery()->getResult();
        }

        return $publishers;
    }

回答1:


your query can be turned into something without a sub-query, but with a join instead, which should be equivalent (and should have the same runtime/complexity)

SELECT u 
FROM user u 
LEFT JOIN user am ON (am.id=u.accountManager) 
WHERE am.roles LIKE '%ROLE_MANAGER%' 
  AND am.accountManager=:managerAdminId
  AND u.roles LIKE '%ROLE_PUBLISHER%'

which can be translated into querybuilder accordingly (I have to assume, that you did not define your associations ... which I find disturbing, but you probably have your reasons):

return $this->createQueryBuilder('u')
  ->leftJoin('App\Entity\User', 'am', 'WITH', 'am.id=u.accountManager')
  ->andWhere('am.roles LIKE :role')
  ->setParameter('role', '%ROLE_MANAGER%')
  ->andWhere('am.accountManager = :managerAdminId')
  ->setParameter('managerAdminId', $managerAdminId)
  ->andWhere('u.roles LIKE :role2')
  ->setParameter('role2', '%ROLE_PUBLISHER%')
  ->getQuery()->getResult();

there is also the options of actually using sub-queries, but using sub-queries imho is always inconvenient - and ugly.

(you might have a look into writing just plain DQL queries, you might feel more at home ...?)




回答2:


According to DQL query examples section within Doctrine's DQL documentation you need to either use EXISTS keyword within DQL query or use exists() method of Expr class.



来源:https://stackoverflow.com/questions/57322563/where-in-query-with-sub-query-in-doctrine-querybuilder-or-equivalent

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!