我正在尝试并且未能将我相对简单的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
有多个条目具有相同的名称,但分数不同。我想只显示每个名字的“高分”。我一直在尝试一两天,没有运气。有人能指出我正确的方向吗?
答案 0 :(得分:8)
您尝试使用doctrine的查询与greatest-n-per-group相关。要使用子查询然后与主查询连接,要使用doctrine来处理复杂的事情。所以下面是重写的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
要将上述查询转换为等同于doctrine或DQL很容易,下面是上面SQL的DQL版本:
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
或者使用查询构建器,您可以使用DEMO Schema
编写类似我在下面使用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中创建一个实体将视图名称放在表注释中,然后开始调用您的实体,它将给出查询返回的结果,但不推荐这种方法暂时解决。
答案 1 :(得分:2)
Inner Join语句需要第一个参数作为表,这是查询中的语义错误。
$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");
答案 2 :(得分:2)
使用它 在课堂上
$name = $em->getRepository('AppBundle:BlogPost')->getMaxId();
在存储库中,您可以使用类似
的内容 public function getMaxId()
{
$qb = $this->createQueryBuilder('u');
$qb->select('u, MAX(id) as idMax');
return $qb->getQuery()->getSingleResult();
}
答案 3 :(得分:0)
:
语法。如果ShmupBundle:Score
应该是数据库和表,那么使用.
。如果Doctrine应该用某些东西代替它,那么它用它做什么呢?GROUP BY
子句,它必须是之后的<{em} WHERE
子句。请尝试删除GROUP BY b.name
。GROUP BY
和b.name
都不需要a.name
,因为它们是平等的。