Как фильтровать по внешнему ключу, который сгруппирован?

Модель:

from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=100)


class Result(models.Model):
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    outcome = models.IntegerField()
    time = models.DateTimeField()

Sql:

select * from person as p
inner join (
   select person_id, max(time) as max_time, outcome from result
   group by person_id
) r on p.id = r.person_id
where r.result in (2, 3)

Я хочу получить все записи о человеке, где последний результат был 2 или 3. Я добавил необработанный sql выше для дальнейшего объяснения.

Я рассмотрел использование подзапроса для фильтрации записей о людях, имеющих совпадающий id результата

sub_query = Result.objects.values("person_id").annotate(max_time=Max("time"))

однако использование значений вычеркивает другие поля.

Идеально я мог бы сделать это в кверисете одного человека, но я не думаю, что это тот случай.

Думаю, вы можете сделать это напрямую....

from django.db.models import Q

results = Results.objects.filter(Q(outcome=3) | Q(outcome=2))

person = []
for result in results:
 person += [result.person]

Поскольку у человека может быть несколько записей результатов, а я хочу проверить только последнюю запись, A subquery был единственным способом, который я смог найти для этого

last_result = Subquery(
    Result.objects.filter(person_id=OuterRef("pk")).order_by("-time").values("result")[:1]
)

people = Person.objects.all().annotate(max_time=Max("result__time"), current_result=last_result).filter(current_result__in=[2,3)

Сначала я создаю подзапрос, который возвращает последнюю запись результата. Затем я добавляю это поле в запрос people, чтобы можно было отфильтровать по нему только результаты с 2 или 3.

Это означало, что он будет возвращать только те записи о людях, где текущий результат равен 2 или 3.

Вернуться на верх