Doctrine orm 原则2:子查询别名在结果中创建额外级别

Doctrine orm 原则2:子查询别名在结果中创建额外级别,doctrine-orm,Doctrine Orm,考虑以下DQL: SELECT a, (SELECT COUNT(c.id) FROM Comment c WHERE c.article_id = a.id) num_comments FROM Article a 我希望结果包含所有文章列以及同一级别上的num_注释,但文章列被包装在索引0处的数组中: array( 0 => array( 0 => array( "id" => 1, "title" => "Title",

考虑以下DQL:

SELECT
  a,
  (SELECT COUNT(c.id) FROM Comment c WHERE c.article_id = a.id) num_comments
FROM Article a
我希望结果包含所有文章列以及同一级别上的num_注释,但文章列被包装在索引0处的数组中:

array(
  0 => array(
    0 => array(
      "id" => 1,
      "title" => "Title",
    ),
    "num_comments" => 15
  ),
  1 => array(
    0 => array(
      "id" => 2,
      "title" => "Title",
    ),
    "num_comments" => 20
  )
);

如何将所有文章列和任何额外字段保持在同一级别?

@hari提到的内容与答案非常接近

你只需要做一个左连接,这样你就可以得到所有的文章,即使他们没有评论

 SELECT a, COUNT(c.id) AS num_comments FROM Article a LEFT JOIN a.comments c GROUP BY a.id 
为了使计数与文章中的相同数组中,我会说分别按字段进行选择

SELECT a.id, a.text, a.date, COUNT(c.id) AS num_comments FROM Article a LEFT JOIN a.comments c GROUP BY a.id 

我将把我的答案分成简短和冗长的解释(以及备选答案)

简短解释:

SELECT a.field1
     , ...
     , a.fieldN
     , (SELECT COUNT(c.id) FROM Comment c WHERE c.article_id = a.id) num_comments 
  FROM Article a
然后作为数组,它将返回您期望的结果

详细解释:

SELECT a.field1
     , ...
     , a.fieldN
     , (SELECT COUNT(c.id) FROM Comment c WHERE c.article_id = a.id) num_comments 
  FROM Article a
无论何时引用实体本身(在本例中为“SELECT a”),这意味着您请求返回与任何其他元素隔离的整个实体。 默认情况下,原则始终将此实体分配给索引0,并根据您选择的实体数量继续分配。要更改此行为,您所要做的就是为实体添加别名,就像对子查询所做的那样:

SELECT a AS article
     , (SELECT COUNT(c.id) FROM Comment c WHERE c.article_id = a.id) AS num_comments 
  FROM Article a
这将回到类似于:

array(
  0 => array(
    "article" => array(
      "id" => 1,
      "title" => "Title",
    ),
    "num_comments" => 15
  ),
  1 => array(
    "article" => array(
      "id" => 2,
      "title" => "Title",
    ),
    "num_comments" => 20
  )
);
如果希望不返回整个实体,可以使用部分支持,只返回感兴趣的字段。让我们支持您只需要id(强制,因为它是实体标识符)和标题:

SELECT PARTIAL a.{id, title} AS article
     , (SELECT COUNT(c.id) FROM Comment c WHERE c.article_id = a.id) AS num_comments 
  FROM Article a
另一种方法是将结果封装到DTO中。当您决定将值作为对象时,这将提供更多的OO控制。DQL将如下所示:

SELECT NEW ArticleDTO(a, COUNT(c.id)) 
  FROM Article a
  LEFT JOIN a.comments c
 GROUP BY a.id
无法将整个子查询作为参数放置的原因是由于DQL的限制。没有人请求过完整的子查询,所以现在我们遵循JPA建议的ScalarExpression

干杯


Guilherme Blanco应该给你一个答案。从文章a中选择a,将(c.id)计数为num_注释,并按a加入a.comments c组。id@HariKT但是我不能得到没有评论的文章。如果我使用“selecta.id”,一切正常,所以我知道这不是SQL问题。当我获取所有文章列时,我的结果不正确。这将限制我只使用一个聚合函数。这是一个很好的解决方法,但我喜欢扩展我的查询,因为我总是添加需要额外数据的新功能。我们可以在DQL中使用以下符号:“AS a.num_comments”,以便标量可以与结果数组中的其他文章列处于同一级别吗?如果这需要更多的讨论,我会开一张罚单。