Язык запросов Doctrine get Max / Latest Row Per Group

Я пытаюсь и не могу перевести свой относительно простой оператор SQL в тот, который будет работать в Doctrine.

Это оператор SQL, который работает по мере необходимости при работе с моей базой данных:

SELECT a.* FROM score a INNER JOIN ( SELECT name, MAX(score) AS highest FROM score GROUP BY name ) b ON a.score = b.highest AND a.name = b.name GROUP BY name ORDER BY b.highest DESC, a.dateCreated DESC 

Вот попытка DQL:

 $kb = $em->createQuery( "SELECT a FROM ShmupBundle:Score a INNER JOIN a.name ShmupBundle:Score b WITH a.score = b.score AND a.name = b.name GROUP BY b.name WHERE a.platform='keyboard' GROUP BY a.name ORDER BY b.score DESC, a.dateCreated DESC" ); 

Что в настоящее время дает эту ошибку:

 [Semantical Error] line 0, col 73 near 'ShmupBundle:Score': Error: Class ShmupBundle\Entity\Score has no association named name 

Сама таблица довольно проста: id, name, score, platform, dateCreated

Есть несколько записей с тем же именем, но разные баллы. Я хочу показать только «высокую оценку» за каждое имя. Я пробовал в течение дня или двух, без везения. Может кто-то указать мне верное направление?

Solutions Collecting From Web of "Язык запросов Doctrine get Max / Latest Row Per Group"

Запрос, который вы пытаетесь сделать с доктриной, связан с наибольшей-n-на-группой . Чтобы использовать вспомогательный запрос, а затем присоединиться к основному запросу, вам сложно справиться с доктриной. Ниже приведена перезаписанная версия SQL для получения тех же результатов без использования каких-либо агрегатных функций

 SELECT a.* FROM score a LEFT JOIN score b ON a.name = b.name AND a.score < b.score WHERE b.score IS NULL ORDER BY a.score DESC 

DEMO

Для преобразования вышеуказанного запроса, эквивалентного доктрине или DQL, легко, ниже приведена версия DQL выше SQL

 SELECT a FROM AppBundle\Entity\Score a LEFT JOIN AppBundle\Entity\Score b WITH a.name = b.name AND a.score < b.score WHERE b.score IS NULL ORDER BY a.score DESC 

Или с построителем запросов вы можете написать что-то вроде того, что я тестировал ниже с помощью symfony 2.8, используя схему DEMO

 $DM = $this->get( 'Doctrine' )->getManager(); $repo = $DM->getRepository( 'AppBundle\Entity\Score' ); $results = $repo->createQueryBuilder( 'a' ) ->select( 'a' ) ->leftJoin( 'AppBundle\Entity\Score', 'b', 'WITH', 'a.name = b.name AND a.score < b.score' ) ->where( 'b.score IS NULL' ) ->orderBy( 'a.score','DESC' ) ->getQuery() ->getResult(); 

Другая идея – создать представление, используя ваш запрос в базе данных, а в symfony создать объект, который помещает имя представления в аннотацию таблицы и только начинать вызывать вашу сущность, он даст результаты, возвращенные вашим запросом, но этот подход не рекомендуется просто временное исправление ,

Inner Join Statement требует первого аргумента в виде таблицы, то есть семантической ошибки в вашем запросе.

 $kb = $em->createQuery( "SELECT a FROM ShmupBundle:Score a INNER JOIN ShmupBundle:Score b ON a.score = b.score AND a.name = b.name GROUP BY b.name WHERE a.platform='keyboard' GROUP BY a.name ORDER BY b.score DESC, a.dateCreated DESC"); 
  • MySQL не понимает синтаксис : Если ShmupBundle:Score должен быть базой и таблицей, тогда используйте . , Если Доктрина должна что-то заменить, то что с ней делать?
  • Может быть только одно предложение GROUP BY , и оно должно быть после WHERE . Попробуйте удалить GROUP BY b.name .
  • Нет необходимости в GROUP BY и b.name и a.name так как они равны.

использовать это в классе

  $name = $em->getRepository('AppBundle:BlogPost')->getMaxId(); 

в репозитории вы можете использовать что-то вроде

  public function getMaxId() { $qb = $this->createQueryBuilder('u'); $qb->select('u, MAX(id) as idMax'); return $qb->getQuery()->getSingleResult(); }