首页 > 解决方案 > 在 JOIN 中向 Doctrine Query Builder 添加排除项

问题描述

我在 Symfony 应用程序中使用 Doctrine Query Builder 构建了以下查询。

    $qb->select('c')
        ->from('AppBundle:Course', 'c')
        ->join('AppBundle:Log', 'a', Expr\Join::WITH, $qb->expr()->eq('c.id', 'a.course'))
        ->where($qb->expr()->in('a.type', ':type'))
        ->andWhere($qb->expr()->between('a.time', ':start', ':end'))
        ->andWhere($qb->expr()->eq('c.status', ':status'))
        ->setParameter(':type', ['opened'])
        ->setParameter(':standardScratchScore', [74])
        ->setParameter(':status', Course::OPENED)
        ->setParameter(':start', $dateFrom->format('Y-m-d H:i:s'))
        ->setParameter(':end', $dateTo->format('Y-m-d H:i:s'))
    ;

在我的代码中,我遍历Courses ,然后再次查询Log表以检查是否不存在具有特定类型的条目Courselog.type = 'log.sent-email' 有没有一种方法可以将本课程的排除合并到此初始查询中,而无需使用子选择之类的东西?

在循环中再次查询同一个表对我来说不是最理想的,NewRelic 认为它会损害我的应用程序的性能。

标签: postgresqlsymfonyjoindoctrinedql

解决方案


好吧,您总是可以再加入一次来满足这一特定需求:

$qb->select('c')
    ->from('AppBundle:Course', 'c')
    ->join('AppBundle:Log', 'a', Expr\Join::WITH, $qb->expr()->eq('c.id', 'a.course'))
    ->leftjoin(
        'AppBundle:Log', 
        'b', 
        Expr\Join::WITH, 
        $qb->expr()->andx(
            $qb->expr()->eq('c.id', 'b.course'),
            $qb->expr()->eq('b.type', 'log.sent-email')
        ))          
    ) // join log a second time, with the type condition
    ->where($qb->expr()->in('a.type', ':type'))
    ->andWhere($qb->expr()->between('a.time', ':start', ':end'))
    ->andWhere($qb->expr()->eq('c.status', ':status'))
    ->andWhere($qb->expr()->isNull('b.type')) // Only select records where no log record is found
    ->setParameter(':type', ['opened'])
    ->setParameter(':standardScratchScore', [74])
    ->setParameter(':status', Course::OPENED)
    ->setParameter(':start', $dateFrom->format('Y-m-d H:i:s'))
    ->setParameter(':end', $dateTo->format('Y-m-d H:i:s'))
;

推荐阅读