在 Django 中,考虑以下模型类,
class Report(models.Model):
owner = models.ForeignKey(
to=Owner,
on_delete=models.CASCADE,
related_name='data',
)
balance = models.PositiveIntegerField()
report_date = models.DateField()
假设这张表只有以下四项,
<QuerySet [{'owner': 1, 'balance': 100, 'report_date': datetime.date(2023, 3, 4)}, {'owner': 1, 'balance': 50, 'report_date': datetime.date(2023, 3, 9)}, {'owner': 2, 'balance': 1000, 'report_date': datetime.date(2023, 2, 2)}, {'owner': 2, 'balance': 2000, 'report_date': datetime.date(2023, 2, 22)}]>
由
owner
和聚合report_date
的最小值的简单组如下,
Report.objects.values('owner').annotate(min_report_date=Min('report_date')).values('owner', 'min_report_date')
结果如下,
<QuerySet [{'owner': 1, 'min_report_date': datetime.date(2023, 3, 4)}, {'owner': 2, 'min_report_date': datetime.date(2023, 2, 2)}]>
现在我想返回对应于
balance
字段的最小值的 report_date
除了像下面这样的 owner
和 min_report_date
字段,
<QuerySet [{'owner': 1, 'min_report_date': datetime.date(2023, 3, 4), 'balance': 100}, {'owner': 2, 'min_report_date': datetime.date(2023, 2, 2), 'balance': 1000}]>
我的尝试是下面的 Django 查询,
Report.objects.values('owner').annotate(min_report_date=Min('report_date')).values('owner', 'min_report_date', 'balance')
但是结果失去了聚合的效果(即返回了所有行),如下所示,
<QuerySet [{'owner': 1, 'balance': 50, 'min_report_date': datetime.date(2023, 3, 9)}, {'owner': 1, 'balance': 100, 'min_report_date': datetime.date(2023, 3, 4)}, {'owner': 2, 'balance': 2000, 'min_report_date': datetime.date(2023, 2, 22)}, {'owner': 2, 'balance': 1000, 'min_report_date': datetime.date(2023, 2, 2)}]>
Subquery
表达式[Django-doc]:
from django.db.models import OuterRef, Subquery
Owner.objects.annotate(
min_report_balance=Subquery(
Report.objects.filter(owner_id=OuterRef('pk'))
.order_by('report_date')
.values('balance')[:1]
)
)
从该查询集中产生的
Owner
对象将具有一个额外的属性 min_report_balance
,即该所有者的“最旧”balance
的 Report
,或者 None
(NULL
) 如果没有这样的报告存在。