【问题标题】:Django aggregation and annotation behavior comparisonDjango 聚合和注解行为比较
【发布时间】:2017-07-18 09:03:03
【问题描述】:

我试图使用带注释的值来过滤使用 F 表达式的查询集,但事实证明它的行为不符合我的预期。

我正在尝试从查询集 qs 中过滤对象,其属性 some_prop 是该查询集的最大值。例如:

set(qs.values_list('some_prop', flat=True))

会输出:

set([1, 3, 5, 7, 9])

我的目标是按值 9 过滤 qs,这是最大值。我可以使用聚合轻松实现:

max_prop = qs.aggregate(max_prop=Max('some_prop'))['max_prop']
qs.filter(some_prop=max_prop)

但我想将这种行为浓缩在一个查询中,所以我使用了注解而不是聚合:

qs.annotate(max_prop=Max('some_prop')).filter(some_prop=F('max_prop'))

但是,这并没有表现出相同的行为。这实际上只是按所有 some_prop 值而不是最大值进行过滤。

我错过了什么?注释和聚合功能一定是我误解了一些东西。

【问题讨论】:

    标签: python django


    【解决方案1】:

    由于您的注释不采用一对多关系中的值,因此相关对象集中的最大值将被注释到与该集合相关的对象,Max(对于每个对象)是仅采用一个值 - some_prop - 并附加到查询集中的每个对象;这与直接访问/过滤some_prop 没有什么不同:

    当指定annotate() 子句时,QuerySet 中的每个对象 将使用指定的值进行注释。

    对于单个表,您需要先聚合以获取最大值,然后对该值进行过滤。

    【讨论】:

    • 所以我无法通过annotate在单个查询中实现我所追求的行为?
    • @dabadaba 有一种变通方法是使用.values 将所有对象归为一个并获取最终最大值:stackoverflow.com/questions/9838264/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-12
    • 2018-07-06
    • 2023-03-07
    • 2016-11-18
    • 2019-06-06
    • 2021-01-20
    • 2011-07-07
    相关资源
    最近更新 更多