WHERE ... 在 Doctrine queryBuilder 或等效的子查询中进行查询
WHERE ... IN query with sub-query in Doctrine queryBuilder or equivalent
在我的 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;
}
根据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.
你的查询可以变成没有子查询的东西,但是有一个连接,它应该是等价的(并且应该有相同的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%'
可以相应地翻译成查询生成器(我必须假设,你没有定义你的关联......我觉得这很令人不安,但你可能有你的理由):
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 查询,您可能会感觉更自在......?)
在我的 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;
}
根据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.
你的查询可以变成没有子查询的东西,但是有一个连接,它应该是等价的(并且应该有相同的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%'
可以相应地翻译成查询生成器(我必须假设,你没有定义你的关联......我觉得这很令人不安,但你可能有你的理由):
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 查询,您可能会感觉更自在......?)