Я создаю приложение в Symfony 1.4 и Doctrine 1.2 ORM. Я довольно новичок в доктрине ORM, и я овладеваю ею, но я не могу полностью решить эту проблему.
У меня есть таблица оценок пользователей (mbScoreByGenre), где один идентификатор пользователя может иметь несколько записей оценок пользователей для одного 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 }
A. Сначала я попытался сделать что-то вроде этого:
$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', прерывание! в \ lib \ vendor \ symfony-1.4.14 \ lib \ plugins \ sfDoctrinePlugin \ lib \ vendor \ doctrine \ Doctrine \ Query \ Tokenizer.php в строке 303. Я не понимаю, как построить подзапрос, чтобы он работал.
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, заключается в том, что я прочитал, что доктрина 1.2 не поддерживает подзапросы в From. Для этого подхода я не мог понять, как ссылаться на столбец «total_score» в формате tableAlias.fieldName. Нужно ли добавлять пустой компонент, который ссылается на таблицу подзапросов, возвращенную для 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 относятся к одной и той же модели?
Я провел множество поисков ответов в Интернете, но, похоже, не могу найти ответы ни для одного из трех подходов.
Любая помощь будет отличной. Цени это.