如何在 Doctrine Query Builder 中 improve/rewrite 这个查询(不在子查询中)

How to improve/rewrite this query in Doctrine Query Builder (NOT IN with subquery)

我有一个相当简单的原始 SQL 查询,它可以正常工作:

SELECT * FROM set 
WHERE set.is_finalized = 1 
AND set.id NOT IN 
(SELECT set_completion.set_id FROM set_completion WHERE set_completion.user_id = 2)

现在我尝试在 Doctrine Query Builder 中获得相同的结果集。 我构建了类似这样的东西,它 也可以工作并给了我正确的结果 :

$subQuery = $this->_em->createQueryBuilder();
$subQueryResult = $subQuery
            ->select('IDENTITY(c.set)')
            ->from('App\Entity\SetCompletion', 'c')
            ->where('c.user = :user')
            ->setParameter('user', $user)
            ->getQuery()
            ->getArrayResult()
        ;
        
return $this->createQueryBuilder('s')
            ->andWhere('s.isFinalized = :finalized')
            ->andWhere('s.id not in (:completions)')
            ->setParameter('finalized', true)
            ->setParameter('completions', $subQueryResult)
            ->orderBy('s.id', 'DESC')
            ->getQuery()
            ->getResult()
        ;

但是我确实觉得这看起来过于复杂而且不是很干净。为了学习,有没有办法用不那么臃肿的东西来达到同样的结果?也许在单个查询中使用 JOIN-s?有时,当涉及到比简单的包容性条件更多的东西时,我根本无法理解 DQL/Builder 中的加入结果。

将您的“相当简单的原始 SQL 查询,按我的意愿工作”转换为

SELECT set.* 
FROM set 
LEFT JOIN set_completion ON set.id = set_completion.set_id
                        AND set_completion.user_id = 2
WHERE set.is_finalized = 1 
  AND set_completion.set_id IS NULL

然后构建此查询的 DQL 表示。