Я пытаюсь и не могу перевести мой относительно простой оператор 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
Сама таблица довольно проста:
идентификатор, имя, оценка, платформа, дата создания
Есть несколько записей с одним и тем же именем, но разные оценки. Я хочу показать только «высокий балл» по имени. Я пробовал и выключал в течение дня или два без удачи. Может кто-то указать мне верное направление?
Запрос, который вы пытаетесь сделать с доктриной, связан с Наибольший-н-в-группа. Чтобы использовать подзапрос, а затем присоединиться к основному запросу, усложняйте работу с доктриной. Ниже приведена переписанная версия 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
Чтобы преобразовать вышеупомянутый запрос, эквивалентный доктрине или 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, используя ДЕМО Схема
$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 создать сущность, поместить имя представления в аннотацию таблицы и просто начать вызывать вашу сущность, это даст результаты, возвращаемые вашим запросом, но этот подход не рекомендуется просто временное исправление. ,
Внутреннему оператору соединения нужен первый аргумент в виде таблицы, что является семантической ошибкой в вашем запросе.
$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");
использовать этот
в классе
$name = $em->getRepository('AppBundle:BlogPost')->getMaxId();
в репозитории вы можете использовать что-то вроде
public function getMaxId()
{
$qb = $this->createQueryBuilder('u');
$qb->select('u, MAX(id) as idMax');
return $qb->getQuery()->getSingleResult();
}
:
синтаксис. Если ShmupBundle:Score
предполагается, что база данных и таблица, а затем использовать .
, Если Доктрина должна заменить это чем-то, то что она делает с этим?GROUP BY
пункт, и это должно быть после WHERE
пункт. Попробуйте удалить GROUP BY b.name
,GROUP BY
и то и другое b.name
а также a.name
так как они равны.