我正在使用Symfony 1.4和Doctrine 1.2 ORM构建应用程序。我对ORM学说很陌生,并且掌握了它,但我无法解决这个问题。
我有一个用户分数表(mbScoreByGenre),其中一个用户ID可以有一个parent_genre的多个用户分数记录。即 - 多对多
我的目标是根据给定parent_genre_id和user_id的累积分数查找特定用户的排名。我的排名算法使用子查询,我在构建一个有效的学说查询时遇到了很多麻烦。
这是我对mbScoreByGenre
的学说模式mbScoreByGenre:
actAs:
Timestampable: ~
columns:
id: { type: integer, primary: true, autoincrement: true }
user_id: { type: integer, notnull: true }
genre_id: { type: integer, notnull: true }
parent_genre_id: { type: integer, notnull: true }
score: { type: float, notnull: true, default: 0 }
一个。首先,我尝试做这样的事情:
$q = Doctrine_Query::create()
->select('((SELECT COUNT(1) AS num
FROM
(SELECT SUM(mbScoreByGenre.score)
WHERE SUM(mbScoreByGenre.score) > SUM(s.score)
AND mbScoreByGenre.parent_genre_id = '.$genre['parent_id'].'
AND s.parent_genre_id = '.$genre['parent_id'].'
GROUP BY mbScoreByGenre.user_id
) + 1) AS rank')
->from('mbScoreByGenre s')
->where('s.user_id = ?', array($user_id))
->groupBy('s.user_id')
->orderBy('rank');
但我得到以下错误致命错误:达到了'100'的最大功能嵌套级别,正在中止!在第303行的\ lib \ vendor \ symfony-1.4.14 \ lib \ plugins \ sfDoctrinePlugin \ lib \ vendor \ doctrine \ Doctrine \ Query \ Tokenizer.php中。我不明白如何构建子查询以使其工作。
B中。所以我改变并尝试了不同的方法
$q = new Doctrine_RawSql();
$q ->addComponent('s', 'mbScoreByGenre')
->select('COUNT({*}) AS {rank}')
->from('(SELECT SUM(s.score) AS total_score
FROM mb_score_by_genre s
WHERE s.parent_genre_id = '.$genre['parent_id'].'
GROUP BY s.user_id)
')
->where('total_score >= (
SELECT SUM(s.score)
FROM mb_score_by_genre s
WHERE s.parent_genre_id = '.$genre['parent_id'].'
AND s.user_id = '.$user_id.'
GROUP BY s.user_id
)');
但是我收到了这个错误:Sql查询中的所有选定字段必须是格式tableAlias.fieldName。我使用Doctrine_RawSql的原因是我读到,doctrine 1.2不支持From中的子查询。对于这种方法,我无法弄清楚如何引用tableAlias.fieldName格式的“total_score”列。我是否必须添加一个空白组件,该组件引用为“total_score”返回的子查询表?
℃。最后,我尝试将子查询作为一个学说查询运行,并通过计算查询返回的学说对象行来计算排名。
$q = Doctrine_Query::create()
->select('SUM(s.score)')
->from('mbScoreByGenre s')
->where('s.parent_genre_id = ?', $genre['parent_id'])
->andWhere('SUM(s.score) > (
SELECT SUM(p.score)
FROM mbScoreByGenre p
WHERE p.parent_genre_id = '.$genre['parent_id'].'
AND p.user_id = '.$user_id.'
GROUP BY p.user_id
)')
->groupBy('s.user_id');
$result = $q->execute();
但它给了我错误:
SQLSTATE [HY000]:常规错误:1111无效使用组功能。是因为groupBy('s.user_id')和GROUP BY p.user_id,p和s都引用相同的模型?
我已经在网上搜索了大量的答案,但我似乎找不到3种方法中任何一种的答案。
任何帮助都会很棒。欣赏它。
答案 0 :(得分:2)
也许,我并不完全明白你真正需要什么,但你是否尝试过HAVING条款? WHERE子句不支持SUM()等聚合函数。 我尝试了这个代码并且它工作并返回了一些值,但我不能确定这是否是你需要的:
$q = Doctrine_Query::create()
->select('count(*)')
->from('mbScoreByGenre s')
->where('s.parent_genre_id = ?', $genre['parent_id'])
->having("SUM(s.score) > (
SELECT SUM(p.score)
FROM mbScoreByGenre p
WHERE p.parent_genre_id = {$genre['parent_id']}
AND p.user_id = {$user_id})")
->groupBy('s.user_id');
$result = $q->execute(array(), Doctrine::HYDRATE_SCALAR);
var_dump($result);
如果这不是您所需要的 - 请尝试更准确地解释。
答案 1 :(得分:0)
您不应该使用原始sql将子查询嵌套到条件(或在您的情况下)。而是使用createSubquery()
明确告诉有关子查询的学说。这也将帮助您在更复杂的场景中,其中doctrine不能再处理深层嵌套的原始SQL查询。所以你的查询应该是这样的:
$q = Doctrine_Query::create()
->select('count(*)')
->from('mbScoreByGenre s')
->where('s.parent_genre_id = ?', $genre['parent_id'])
->groupBy('s.user_id')
;
$subquery = $q->createSubquery()
->select("SUM(p.score)")
->from("FROM mbScoreByGenre p")
->where("p.parent_genre_id = ?", $genre['parent_id'])
->andWhere("p.user_id = ?", $user_id)
;
$q->having("SUM(s.score) > (".$subquery->getDql().")");
另一个例子可以在这里找到:
http://www.philipphoffmann.de/2012/08/taming-doctrine-subqueries/