【问题标题】:WHERE ... IN query with sub-query in Doctrine queryBuilder or equivalentWHERE ... IN 在 Doctrine queryBuilder 或等效项中使用子查询进行查询
【发布时间】:2019-08-02 08:25:13
【问题描述】:

在我的 Symfony 4 项目中,我有一个 User 实体和一个 UserRepository。 我正在尝试在QueryBuilder(Doctrine 2) 甚至在DQL 中实现这个SQL 查询的等效项。

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

或者可能使用不同的语法。

我尝试了不同的方法,但不知道如何使用子查询编写 WHERE ... IN。

这就是我能想到的,但我不喜欢它,因为它会触发多个查询,我可以用一个查询来做一些事情:

    //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;
    }

【问题讨论】:

标签: symfony doctrine-orm doctrine symfony4 dql


【解决方案1】:

您的查询可以在没有子查询的情况下转换成某种东西,而是使用连接,这应该是等效的(并且应该具有相同的运行时/复杂性)

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%'

可以相应地翻译成查询构建器(我不得不假设您没有定义您的关联......我觉得这很令人不安,但您可能有您的理由):

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

实际上还有using sub-queries 的选项,但使用子查询恕我直言总是不方便 - 并且丑陋。

(您可能会考虑编写简单的 DQL 查询,您可能会觉得更自在...?)

【讨论】:

  • 你是对的,这是一个更简单的语法。 (WHERE am.roles LIKE '%ROLE_PUBLISHER%'应该是'%ROLE_MANAGER%')。Tx!!
【解决方案2】:

根据 Doctrine 的 DQL 文档中的 DQL query examples section,您需要在 DQL 查询中使用 EXISTS 关键字或使用 Expr 类的 exists() 方法。

【讨论】:

    猜你喜欢
    • 2011-10-02
    • 2015-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多