SQL 学说:InnerJoin 其中 A.key = B.key 或 A.key = NULL

SQL Doctrine: InnerJoin where A.key = B.key or A.key = NULL

我正在尝试使用 Doctrine 进行 "complex" SQL 请求: 我有一个有多个代表团的体育项目。 我创建了事件 ('e') 来告诉每个事件接下来会发生什么。

一个事件可以代表多个代表团,如果是代表所有人,它就没有链接到任何人(保存数据库space) 然后我在 Events 和 Delegations 之间建立了 ManyToMany 关系

我想在现在(->where('e.startTime > :date'))之后获取与一个代表团('A')有关的所有事件 此事件由以下链接:

->innerJoin('e.delegations', 'd', 'WITH', 'd.name = A' )

这项工作非常好,但对于没有任何代表团的事件,它不会得到 returned 然后我试了:

->leftJoin('e.delegations', 'd', 'WITH', 'd.name = A' )

但这return所有事件

然后我需要添加一个 orWhere 来捕获 e.delegations = null 但我不知道如何使用它,因为这会打破之前关于时间的地方。 或者也许我可以在 innerJoin 中指定一些东西(比如 a 或 NULL 或其他东西)但我没有在任何 Doctrine QueryBuilder Doc 中找到它 我在法语中找到了 this,但这只是一个连接并使用 Where 选择,那么与 inner/left 连接相比,它肯定不是最佳选择,并且更难维护。

问题

这个问题是个小技巧,因为一旦我们按名称 (d.name = A) 过滤委派,就所有目的而言,任何没有该委派但有其他委派的事件 (e),将被视为没有。因为过滤器会"remove"其他委托被返回。

解决方案

使用子查询解决这个问题:

//subquery - only returns event which has delegation 'A'
$sqb->select('e1.id')
    ->from('MyNamespace\Entity\Event','e1')
    ->innerJoin('e1.delegations', 'd', 'WITH', "d.name = 'A'");

//main query 
$qb
   ->leftJoin('e.delegations', 'd')       
   ->andWhere('e.delegation is null or e.id in ('.$sqb->getDQL().')'); 

PS
如果您需要在子查询中使用占位符 (:param),请始终在主 QueryBuilder 中设置参数。