7

我有一个模型 XYZ,我需要获取给定查询集的字段 a、b 和表达式 x/y 的最大值。

它非常适合田野。就像是:

>>> XYZ.all().aggregate(Max('a'))

... {'a__max': 10}

但是,我找不到表达式的方法。尝试类似:

>>> XYZ.all().aggregate(Max('x/y'))

给出一个错误:

*** FieldError: Cannot resolve keyword 'x/y' into field. Choices are: a, b, x, y, id

尝试类似:

>>> XYZ.all().aggregate(Max(F('x')/F('y')))

给出一个错误:

*** AttributeError: 'ExpressionNode' object has no attribute 'split'

甚至是这样的:

XYZ.all().extra(select={'z':'x/y'}).aggregate(Max('z'))

也不起作用并给出与上述相同的错误:

FieldError: Cannot resolve keyword 'z' into field. Choices are: a, b, x, y, id

我发现这样做的一个技巧是:

XYZ.all().extra(select={'z':'MAX(x/y)'})[0].z

这实际上是有效的,因为它生成了正确的 SQL,但它令人困惑,因为我确实在 z 属性处获得了正确的值,但不是正确的实例,即具有该最大值的实例。

当然,我也可以使用带有 extra() 和 order_by() 的原始查询或技巧,但 Django 一直以一种很好的方式支持聚合查询,但不能支持,这对我来说真的没有意义即使有自己的 F 表达式。

有什么办法吗?

4

4 回答 4

6

在 SQL 中,你想要的其实是

SELECT x/y, * FROM XYZ ORDER BY x/y DESC LIMIT 1;
# Or more verbose version of the #1
SELECT x/y, id, a, b, x, y FROM XYZ GROUP BY x/y, id, a, b, x, y ORDER BY x/y DESC LIMIT 1;
# Or
SELECT * FROM XYZ WHERE x/y = (SELECT MAX(x/y) FROM XYZ) LIMIT 1;

因此在 Django ORM 中:

XYZ.objects.extra(select={'z':'x/y'}).order_by('-z')[0]
# Or
XYZ.objects.extra(select={'z':'x/y'}).annotate().order_by('-z')[0]
# Or x/y=z => x=y*z
XYZ.objects.filter(x=models.F('y') * XYZ.objects.extra(select={'z':'MAX(x/y)'})[0].z)[0]

版本

XYZ.all().extra(select={'z':'MAX(x/y)'})[0].z

没有正确的 x,y 和实例,因为MAX函数是在所有行中评估的,当没有 时GROUP BY,返回的 QuerySet 中的所有实例都将具有相同的值zas MAX(x/y)

于 2012-04-19T14:31:02.460 回答
3

F()自 Django 1.8 起,您使用对象的示例应该可以正常工作:

XYZ.all().aggregate(Max(F('x')/F('y')))

有一个片段演示了Django 聚合备忘单Sum()中的和F()对象的聚合:

Book.objects.all().aggregate(price_per_page=Sum(F('price')/F('pages'))
于 2016-01-05T23:00:27.103 回答
0

对于低于 1.8 的版本,您可以通过这种(未记录的)方式实现相同的目的。

Book.objects.all().aggregate(price_per_page=Sum('price_per_page', 
                                                field='book_price/book_pages'))

这适用于 Postgres,我不了解 MySQL。

资料来源:Django 聚合:两个字段相乘的总和

于 2016-06-03T14:04:16.270 回答
-3

我认为您应该分别获得最大值

result = XYZ.aggregate(Max('x'), Max('y'))

然后划分两个字段

result['x__max'] \ result['y__max']
于 2012-04-19T05:30:24.923 回答