У меня есть простая двунаправленная связь «один ко многим» между 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]: Syntax error or access violation: 1055 Expression #5 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'test.v1_.score' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with 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(), все работает нормально. Я все еще прошу помощи, так как Twig по-видимому использует getIterator() за циклом for, когда $pag передается в шаблон.ORDER BY, тоже все работает нормально!sql_mode=ONLY_FULL_GROUP_BY и НЕ хочу его менять.





В этом случае вы не выбираете объединенную коллекцию «ко многим», вы группируете по Идентификатор элемента и просто агрегируете значения отношения «валорасионес».
Согласно Документация по страницам доктрины, в этом случае вы можете отключить флаг $fetchJoinCollection:
$pag = new Paginator($itemsQb, false);
Кажется, проблема вызвана тем, что доктрина пытается добавить «отсутствующие поля» из порядка по условию в предложение выбора. Связанная проблемаЗапрос на вытягивание
В этом случае он считает, что должен добавить «v.score» к выбору.
В качестве альтернативы вы можете отключить использование обходчиков вывода в пагинаторе, чтобы избежать описанного выше поведения:
$pag->setUseOutputWalkers(false);
В качестве примечания: в Twig, по-видимому, при повторении результата getQuery()->getResult(), хотя он содержит текущие элементы страницы, переменные loop будут содержать неожиданные значения; loop.length выдаст общее количество элементов вместо количества элементов для текущей страницы; и loop.last не будет истинным для последнего элемента коллекции, а не для последнего элемента страницы.
Спасибо! Упомянутая вами проблема говорит о том, что она должна быть исправлена в 2.7, но ошибка все еще здесь.
Инициализация пагинатора с помощью
$fetchJoinCollection = falseсделала свое дело! Теперь итератор работает отлично.