以前记录的 Django 子查询子集
Django Subquery Subset of Previous Records
我正在尝试使用先前行的子集的集合来注释查询集。以下例 table 球员在特定比赛中的得分,其中 last_2_average_score 列是前两场比赛得分的滚动平均值播放器。
+----------+-----------+---------+-------------------------+
| date | player | score | last_2_average_score |
+----------+-----------+---------+-------------------------+
| 12/01/19 | 1 | 10 | None |
| 12/02/19 | 1 | 9 | None |
| 12/03/19 | 1 | 8 | 9.5 |
| 12/04/19 | 1 | 7 | 8.5 |
| 12/05/19 | 1 | 6 | 7.5 |
+----------+-----------+---------+-------------------------+
为了实现这一点,我编写了以下查询,试图用相应的 2 场比赛平均得分
对每个 "row" 进行注释
ScoreModel.objects.annotate(
last_two_average_score=Subquery(
ScoreModel.objects.filter(
player=OuterRef("player"), date__lt=OuterRef("date")
)
.order_by("-date")[:2]
.annotate(Avg("score"))
.values("score__avg")[:1],
output_field=FloatField(),
)
)
然而,这个查询并没有输出正确的结果。事实上,结果只是用
注释的每条记录
{'last_two_average_score': None}
我尝试了多种不同的查询组合,都找不到正确的组合。如果您能提供任何建议,我们将不胜感激!
我没有首先尝试从 ORM 解决问题,而是转回头来首先尝试在原始 SQL 中实现查询。这立即让我想到了 WINDOW 函数的概念,当我查看 Django 的 ORM 时,很快就找到了。
https://docs.djangoproject.com/en/3.0/ref/models/expressions/#window-functions
对于这个感兴趣的人,结果查询看起来像这样,这比我试图用子查询
完成的要简单得多
ScoreModel.objects.annotate(
last_two_average=Window(
expression=Avg("score"),
partition_by=[F("player")],
order_by=[F("date").desc()],
frame=RowRange(start=-2, end=0),
)
)
我正在尝试使用先前行的子集的集合来注释查询集。以下例 table 球员在特定比赛中的得分,其中 last_2_average_score 列是前两场比赛得分的滚动平均值播放器。
+----------+-----------+---------+-------------------------+ | date | player | score | last_2_average_score | +----------+-----------+---------+-------------------------+ | 12/01/19 | 1 | 10 | None | | 12/02/19 | 1 | 9 | None | | 12/03/19 | 1 | 8 | 9.5 | | 12/04/19 | 1 | 7 | 8.5 | | 12/05/19 | 1 | 6 | 7.5 | +----------+-----------+---------+-------------------------+
为了实现这一点,我编写了以下查询,试图用相应的 2 场比赛平均得分
对每个 "row" 进行注释ScoreModel.objects.annotate(
last_two_average_score=Subquery(
ScoreModel.objects.filter(
player=OuterRef("player"), date__lt=OuterRef("date")
)
.order_by("-date")[:2]
.annotate(Avg("score"))
.values("score__avg")[:1],
output_field=FloatField(),
)
)
然而,这个查询并没有输出正确的结果。事实上,结果只是用
注释的每条记录{'last_two_average_score': None}
我尝试了多种不同的查询组合,都找不到正确的组合。如果您能提供任何建议,我们将不胜感激!
我没有首先尝试从 ORM 解决问题,而是转回头来首先尝试在原始 SQL 中实现查询。这立即让我想到了 WINDOW 函数的概念,当我查看 Django 的 ORM 时,很快就找到了。
https://docs.djangoproject.com/en/3.0/ref/models/expressions/#window-functions
对于这个感兴趣的人,结果查询看起来像这样,这比我试图用子查询
完成的要简单得多ScoreModel.objects.annotate(
last_two_average=Window(
expression=Avg("score"),
partition_by=[F("player")],
order_by=[F("date").desc()],
frame=RowRange(start=-2, end=0),
)
)