Django: аннотация суммы по отношению с предельной оговоркой - PullRequest
1 голос
/ 26 июня 2019

У меня есть ситуация, подобная следующей:

class Player(models.Model):
   pass

class Item(models.Model):
   player = models.ForeignKey(Player,
                              on_delete=models.CASCADE,
                              related_name='item_set')
   power = models.IntegerField()

Я хотел бы аннотировать Player.objects.all() с помощью Sum(item_set__power), принимая во внимание только верхний N Item при сортировке по убыванию power.В идеале я хотел бы сделать это с помощью подзапроса, но я не знаю, как это написать.Как это можно сделать?

1 Ответ

2 голосов
/ 27 июня 2019

Это решение, использующее необработанный набор запросов (для меня это было проще реализовать, чем с помощью ORM, но это могло бы быть возможно с ORM с использованием Подзапрос ):

N = 2
query = """
SELECT id,
   (
       SELECT SUM(power) 
         FROM (SELECT power FROM myapp_item WHERE myapp_item.player_id = players.id ORDER BY power DESC LIMIT %s)
   )
   AS power__sum
FROM myapp_player AS players GROUP BY players.id
"""
players = Player.objects.raw(query, [N])

Обновление

Добавление аннотаций невозможно с RawQueryset, но вы можете использовать Выражение RawSQL :

from django.db.models.expressions import RawSQL

N = 2
queryset = Player.objects.all()
query2 = """
SELECT SUM(power) 
  FROM (SELECT  power FROM myapp_item WHERE myapp_item.player_id = myapp_player.id ORDER BY power DESC LIMIT %s)
"""
queryset.annotate(power__sum=RawSQL(query2, (N,)), my_annotation1=..., my_annotation2=...)
...