我在Item
和Valoracion
之间有一个简单的双向一对多关系(评论)。以下查询应按降序获取每个项目的平均分数和评论数:
$itemsQb = $em->getRepository(Item::class)->createQueryBuilder('i')
->select('i as data')
->addSelect('avg(v.score) as avg_score')
->addSelect('count(v.score) as num_reviews')
->leftJoin('i.valoraciones', 'v')
->groupBy('i.id')
->addOrderBy('avg_score', 'DESC')
->addOrderBy('num_reviews', 'DESC');
其中$em
是一个有效的Doctrine\ORM\EntityManager
实例。当使用Doctrine\ORM\Tools\Pagination\Paginator
对上述查询进行分页并使用getIterator()
遍历结果时,将抛出异常,如下所示:
$pag = new Paginator($itemsQb);
// first page, up to three results per page
$pag->getQuery()->setFirstResult(0)->setMaxResults(3);
// display results one by one
echo "Name\t\tAvg\tNum\n";
foreach ($pag->getIterator() as $p) {
echo $p['data']->name . "\t" . $p['avg_score'] . "\t" . $p['num_reviews'] . "\n";
}
SQLSTATE [42000]:语法错误或访问冲突:1055 SELECT列表的表达式#5不在GROUP BY子句中,并且包含非聚合列'test.v1_.score',它在功能上不依赖于GROUP BY子句中的列;这与sql_mode = only_full_group_by不兼容
生成了以下SQL查询
SELECT DISTINCT
id_5
FROM
(SELECT DISTINCT
id_5, sclr_2, sclr_3
FROM
(SELECT
i0_.id AS id_0,
i0_.name AS name_1,
AVG(v1_.score) AS sclr_2,
COUNT(v1_.score) AS sclr_3,
v1_.score AS score_4,
i0_.id AS id_5
FROM
item i0_
LEFT JOIN valoracion v1_ ON i0_.id = v1_.item_id
GROUP BY i0_.id) dctrn_result_inner
ORDER BY sclr_2 DESC , sclr_3 DESC) dctrn_result
LIMIT 3
很明显,v1_.score AS score_4,
线应该不在那里!
那么,为什么生成这个无效的SQL呢?难道我做错了什么?
笔记:
getQuery()->getResult()
而不是getIterator()
一切正常。我仍然在寻求帮助,因为当getIterator()
传递给模板时,Twig显然在for
循环后面使用$pag
。ORDER BY
条款被删除,一切都正常!sql_mode=ONLY_FULL_GROUP_BY
,我不想改变它。在这种情况下,您不会获取已连接的“to-many集合”,您可以按Item ID进行分组,只是聚合“valoraciones”关系的值。
根据doctrine pagination documentation,在这种情况下,您可以禁用$ fetchJoinCollection标志:
$pag = new Paginator($itemsQb, false);
似乎问题是由于学说试图将条件中的“缺失字段”添加到select子句中而引起的。 Related issue Pull request
在这种情况下,它认为它应该向选择添加“v.score”。
或者,您可以禁用分页器中输出walker的使用以避免上述行为:
$pag->setUseOutputWalkers(false);