Doctrine ManyToMany原则联接必须返回一行

Doctrine ManyToMany原则联接必须返回一行,doctrine,many-to-many,dql,Doctrine,Many To Many,Dql,假设你在教义中有一个经典的多人关系。例如,其中一个描述如下: 为了简化示例,只有两种可能的组类型:A或B。一个用户不能属于具有相同类型的两个组。因此,每个用户可以属于0到2个组 现在让我们假设我想为每个用户返回一行(使用getArrayResults()方法不需要,如下所示: ---------------------------------------------------------------------------- | user.id | group_A.type | grou

假设你在教义中有一个经典的多人关系。例如,其中一个描述如下:

为了简化示例,只有两种可能的组类型:A或B。一个用户不能属于具有相同类型的两个组。因此,每个用户可以属于0到2个组

现在让我们假设我想为每个用户返回一行(使用
getArrayResults()
方法不需要,如下所示:

----------------------------------------------------------------------------
| user.id    | group_A.type | group_A.id     | group_B.type | group_B.id   |
----------------------------------------------------------------------------
| 1          | A            | 10             | B            | 20           |
----------------------------------------------------------------------------
| 2          | A            | 10             | B            | 21           |
----------------------------------------------------------------------------
| 3          | A            | 11             | NULL         | NULL         |
----------------------------------------------------------------------------

如何在DQL中转换该结果?我可以使用
innerJoin()
方法获得该结果。如果用户有一个组,则使用
leftJoin()方法
查询返回超过2行。

此类查询的主要问题是类用户和组之间的非系统链接。如果每个用户都链接到每个组,则简单的DQL查询将起作用:

$qb->select('u.id, gA.type, gA.id, gB.type, gB.id')
    ->from('User', 'u')
    ->innerJoin('u.groups', 'gA', 'WITH', 'gA.type = "A"')
    ->innerJoin('u.groups', 'gB', 'WITH', 'gB.type = "B"')
但在上面给出的示例中,结果将是因为用户#3与组#B没有链接:

通过使用leftJoin子句,结果将是一个包含3条以上记录的最大表(上例中为5条)

因此,解决方案是,查询中没有where子句使用combine MAX和groupBy:

$qb->select('u.id, gA.type, max(gA.id), gB.type, max(gB.id)')
    ->from('User', 'u')
    ->innerJoin('u.groups', 'gA', 'WITH', 'gA.type = "A"')
    ->innerJoin('u.groups', 'gB', 'WITH', 'gB.type = "B"')
    ->groupBy('u.id')
这将产生预期的结果:

----------------------------------------------------------------------------
| user.id    | group_A.type | group_A.id     | group_B.type | group_B.id   |
----------------------------------------------------------------------------
| 1          | A            | 10             | B            | 20           |
----------------------------------------------------------------------------
| 2          | A            | 10             | B            | 21           |
----------------------------------------------------------------------------
| 3          | A            | 11             | NULL         | NULL         |
----------------------------------------------------------------------------
如果对查询应用where子句,可以避免:

$qb->select('u.id, gA.type, gA.id, gB.type, gB.id')
    ->from('User', 'u')
    ->innerJoin('u.groups', 'gA', 'WITH', 'gA.type = "A"')
    ->innerJoin('u.groups', 'gB', 'WITH', 'gB.type = "B"')
    ->where('gA.type = 10 AND gB.type = 20)
给出以下结果:

----------------------------------------------------------------------------
| user.id    | group_A.type | group_A.id     | group_B.type | group_B.id   |
----------------------------------------------------------------------------
| 1          | A            | 10             | B            | 20           |
----------------------------------------------------------------------------
$qb->select('u.id, gA.type, gA.id, gB.type, gB.id')
    ->from('User', 'u')
    ->innerJoin('u.groups', 'gA', 'WITH', 'gA.type = "A"')
    ->innerJoin('u.groups', 'gB', 'WITH', 'gB.type = "B"')
    ->where('gA.type = 10 AND gB.type = 20)
----------------------------------------------------------------------------
| user.id    | group_A.type | group_A.id     | group_B.type | group_B.id   |
----------------------------------------------------------------------------
| 1          | A            | 10             | B            | 20           |
----------------------------------------------------------------------------