Symfony框架下Doctrine关联查询:统计未关联ID为1002的Gestionnaire的Utilisateur数量
解决Doctrine关联查询统计问题:排除关联特定Gestionnaire的用户
我明白你的需求:要统计那些完全没有关联ID为1002的Gestionnaire的用户数量,同时还要结合你已有的业务筛选条件(关联特定manager的mouvements、未删除、日期限制等)。
问题分析
你原来的代码里用了内联JOIN关联userGestionnaires和gestionnaire,这会带来两个核心问题:
- 自动过滤掉没有任何
UserGestionnaire关联的用户; - 直接加
sg.id != 1002的条件,会保留那些同时关联了1002和其他Gestionnaire的用户,这不符合你要的"完全未关联1002"的逻辑。
正确的思路是用NOT EXISTS子查询,直接检查当前用户是否存在任何关联到1002的UserGestionnaire记录——如果不存在,就符合你的筛选条件。
修正后的完整代码
public function countUserNoIdSpecificGest() { $limitDate = date_format(new \DateTime("now - 2 years"), 'Y-m-d'); $targetGestionnaireId = 1002; $query = $this->createQueryBuilder('u'); $count = $query ->select('count(distinct(u.id))') // 保留你原有业务的内联JOIN逻辑 ->join('u.mouvements', 'm') ->join('m.rules', 'r') ->join('r.avenantModule', 'am') ->join('am.module', 'mod') ->join('mod.manager', 's') // 核心筛选条件:排除所有关联过1002的用户 ->andWhere($query->expr()->notExists( $this->createQueryBuilder('ug_sub') ->select('1') ->join('ug_sub.gestionnaire', 'sg_sub') ->where('ug_sub.user = u.id') ->andWhere('sg_sub.id = :targetGestionnaireId') ->getDQL() )) // 原有业务筛选条件 ->andWhere('s.id = :managerId') ->andWhere('u.deletedAt IS NULL') ->andWhere('m.deletedAt IS NULL') ->andWhere($query->expr()->gte('m.dateOut', ':limitDate')) // 绑定所有参数 ->setParameter('targetGestionnaireId', $targetGestionnaireId) ->setParameter('managerId', 1002) ->setParameter('limitDate', $limitDate) ->getQuery() ->getSingleScalarResult(); return $count; }
关键部分解释
NOT EXISTS子查询:精准检查当前用户(u.id)是否存在任何UserGestionnaire记录关联到ID为1002的Gestionnaire。如果不存在,条件成立,完全对应你foreach循环里$finded = false的业务逻辑。- 保留原有业务逻辑:没有改动你关联特定manager模块、未删除、日期限制等筛选条件。
- 简化冗余代码:你原来的代码嵌套了两层无意义的
orX,直接简化为单个gte条件即可。
额外说明
这个查询会自动包含那些没有任何UserGestionnaire关联的用户——因为这类用户的子查询不会返回任何结果,NOT EXISTS条件自然成立,完全覆盖你的需求场景。
内容的提问来源于stack exchange,提问作者Wallspirit
相关产品推荐
相关产品推荐

