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