php mysql symfony doctrine greatest-n-per-group

php - Doctrine Query Language obtiene Max/Latest Row por grupo



mysql symfony (4)

Estoy intentando y no puedo traducir mi declaración SQL relativamente simple en una que funcione dentro de Doctrine.

Esta es la instrucción SQL, que funciona según sea necesario cuando se ejecuta en mi base de datos:

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

Aquí está el intento de DQL hasta ahora:

$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" );

Que actualmente está dando este error:

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

La tabla en sí es bastante simple: id, nombre, puntaje, plataforma, fechaCreada

Hay múltiples entradas con el mismo nombre, pero con puntajes diferentes. Quiero mostrar solo el "puntaje alto" por nombre. He estado probando por un día o dos ahora, sin suerte. ¿Alguien puede señalarme en la dirección correcta?


La consulta que intenta hacer con la doctrina está relacionada con la greatest-n-per-group . Para usar una subconsulta y luego unirse con la consulta principal, las cosas son complicadas de manejar con doctrina. A continuación, se muestra la versión SQL reescrita para obtener los mismos resultados sin el uso de ninguna función agregada:

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

Para convertir la consulta anterior equivalente a doctrina o DQL es fácil, a continuación se muestra la versión DQL de SQL anterior:

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

O con el generador de consultas puede escribir algo como lo que he probado a continuación con Symfony 2.8 usando el 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();

Otra idea sería crear una vista usando su consulta en la base de datos y en Symfony crear una entidad, poner el nombre de la vista en la anotación de la tabla y simplemente comenzar a llamar a su entidad, le dará los resultados devueltos por su consulta, pero este enfoque no se recomienda solo una solución temporal .


La declaración de unión interna necesita el primer argumento como tabla, que es un error semántico en su consulta.

$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");


usa esto en clase

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

en el repositorio puedes usar algo como

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


  • MySQL no entiende la sintaxis : Si se supone que ShmupBundle:Score es una base de datos y una tabla, ShmupBundle:Score . . Si se supone que Doctrine lo reemplaza con algo, ¿qué hace con él?
  • Solo puede haber una cláusula GROUP BY , y debe estar después de la cláusula WHERE . Intente eliminar GROUP BY b.name .
  • No hay necesidad de b.name GROUP BY b.name y a.name ya que son iguales.