如何确保Django子查询注解中的正确分组?

mepcadol  于 2023-05-30  发布在  Go
关注(0)|答案(1)|浏览(144)

当我写Django子查询表达式时,有时我不知道Django如何对结果进行分组。
示例:

subquery = (
    RelatedModel.objects.filter(
        category="some_category",
        grandparentmodel=OuterRef("relatedmodel__grandparentmodel"),
        mymodel__created_at__date=OuterRef("created_at__date"),
    )
    .values("grandparentmodel", "mymodel__created_at__date")
    .annotate(net=Sum("mymodel__amount"))
    .values("net")[:1]
)

query = (
    MyModel.objects.annotate(
        net=Coalesce(
            Subquery(subquery), Decimal("0.00")
        )
    )
)

这样,我的目标是将一堆ParentModel示例(类别为"some_category")按grandparentmodelmymodel__created_at__date分组。
这似乎只有在注解之前包含.values("mymodel__created_at__date")时才有效。如果我在net的注解之前没有包含它,子查询仍然运行,只是给出了不正确的net。但是,.values("grandparentmodel")似乎不需要得到正确的分组;我可以排除它,我仍然得到我期望的值。
幕后发生了什么?我如何知道在注解之前使用.values()调用来正确分组?我怎么知道在values()调用中要包括什么?在聚合子查询时,是否有一些经验法则要遵循?

tf7tbtn2

tf7tbtn21#

通常,ORM不是用来构造精确的SQL查询的。它更像是一个工具,可以将您的需求转录成它所能找到的最佳查询。
但是,你找到的是强制分组的方法。

qs = MyModel.objects.all()
qs = qs.values("foo", "bar")  #  Fields used for grouping
qs = qs.annotate(res=Func("baz"))  # Aggregation on other fields

.values()本身将丢弃Model层,并将查询集结果更改为包含作为参数给出的键的dicts。
后面是.annotate(),它包含一个不在.values()参数中的字段上的聚合函数,它将导致一个group by。结果也将是dicts

相关问题