以前记录的 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),
    )
)