【问题标题】:How to filter on a foreign key that is grouped?如何过滤分组的外键?
【发布时间】:2021-12-17 23:40:59
【问题描述】:

型号:

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"))

但是使用值会去除其他字段。

理想情况下,我可以在一个人的查询集中做到这一点,但我认为情况并非如此。

【问题讨论】:

    标签: django django-orm


    【解决方案1】:

    下面的查询排除所有标记不等于 2 OR 3 的人,然后将结果按时间降序排序(最新的将在顶部),最后得到人的详细信息...

    from django.db.models import Q
    
    results = Results.objects.filter(Q(outcome=3) | Q(outcome=2)).order_by('-time').values('person')
    

    【讨论】:

    • 虽然这段代码可以回答问题,但最好包含一些上下文,解释如何它的工作原理和何时 i> 使用它。从长远来看,纯代码的答案没有用处。
    • 许多个人记录将最后一个结果作为另一个值(即 1),在这种情况下应该排除它们。只应返回最后一条记录为 2 或 3 的记录。
    • 已添加简要说明,如果您觉得答案有帮助,请不要犹豫,提前投票,谢谢!!
    【解决方案2】:

    由于一个人可能有多个结果记录,而我只想检查最后一条记录,所以我能找到这样做的唯一方法是 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)
    

    首先我创建一个子查询,它将返回最后一条结果记录。然后我将其添加为人员查询中的一个字段,以便我可以对其进行过滤以仅获得 2 或 3 的结果。

    这是它只会返回当前结果为 2 或 3 的人员记录。

    【讨论】:

      猜你喜欢
      • 2019-07-23
      • 2014-08-13
      • 1970-01-01
      • 2021-07-31
      • 2019-06-18
      • 2021-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多