Мои пользователи в Django могут участвовать в конкурсах, в которых они набирают очки. Я хочу ранжировать своих пользователей по сумме их трех лучших конкурсов. У меня есть рабочий SQL запрос:
SELECT id, sum(contest_points) as plus FROM (
SELECT ROW_NUMBER() OVER (PARTITION BY u.id ORDER BY c.points DESC),
c.points as contest_points, u.id as id
FROM (
user_user AS u
LEFT OUTER JOIN contest_contest AS c ON (u.id = c.user_id)
)
) x
WHERE row_number <= 3
GROUP BY id
ORDER BY plus DESC;
Однако, поскольку есть потенциально много фильтров, которые я хочу применить (страна, тип конкурса), я хочу использовать Django ORM для генерации SQL. Вот где я до сих пор:
Contest.objects.annotate(
rank=Window(expression=Rank(),
partition_by=F('user_id'),
order_by=F('points').desc()
)
Я могу комментировать конкурсы на основе их соответствующего ранга для пользователя, но Django не позволяет мне фильтровать конкурсы на основе ранга, так как вам не разрешено фильтровать после оконной функции. В чистом SQL это не проблема, так как я могу просто обернуть весь запрос. Это невозможно в Django, поскольку подзапросу разрешено возвращать только один столбец. Моя идея состоит в том, чтобы пользовательским образом обернуть внутренний SQL, сгенерированный Django, с помощью
SELECT id, sum(contest_points) as plus FROM (
и
WHERE row_number <= 3
GROUP BY id
ORDER BY plus DESC
и эффективно использовать запрос Django в качестве внутреннего запроса. Однако я не нашел способа обернуть запрос Django пользовательским кодом SQL. Использование запроса. str () и добавление my SQL не работает, так как окончательный SQL применяется только Django на уровне базы данных.