考虑以下DQL:
SELECT
a,
(SELECT COUNT(c.id) FROM Comment c WHERE c.article_id = a.id) num_comments
FROM Article a
我希望结果包含所有文章列和同一级别的num_comments,但是文章列包含在索引0的数组中:
array(
0 => array(
0 => array(
"id" => 1,
"title" => "Title",
),
"num_comments" => 15
),
1 => array(
0 => array(
"id" => 2,
"title" => "Title",
),
"num_comments" => 20
)
);
如何将所有文章列和任何额外字段保持在同一级别?
答案 0 :(得分:3)
我将在短期和长期解释(和替代答案)中分开我的答案。
简短说明:
SELECT a.field1
, ...
, a.fieldN
, (SELECT COUNT(c.id) FROM Comment c WHERE c.article_id = a.id) num_comments
FROM Article a
然后保湿作为ARRAY,它将返回你期待的东西。
长解释:
无论何时引用实体本身(在您的情况下,“SELECT a”),这意味着您要求返回与任何其他元素隔离的整个实体。 默认情况下,Doctrine总是将此实体分配给索引0并继续,具体取决于您选择的FROM实体的数量。要更改此行为,您所要做的就是为实体添加别名,就像使用子查询一样:
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
)
);
如果您不想返回整个实体,可以使用PARTIAL支持并仅返回您感兴趣的字段。让我们支持您只需要id(必需,因为它是实体标识符)和标题:< / p>
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
答案 1 :(得分:0)
@hari提到的非常接近答案。
你只需要进行LEFT JOIN即可获得所有文章,即使他们没有评论。
SELECT a, COUNT(c.id) AS num_comments FROM Article a LEFT JOIN a.comments c GROUP BY a.id
并且将COUNT与文章放在同一个数组中,我会单独按字段说SELECT。
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