Ped*_*eck 7 python sql django django-1.3
我有一个模型XYZ,我需要获得给定查询集的字段a,b和表达式x/y的最大值.
它适用于田野.就像是:
>>> XYZ.all().aggregate(Max('a'))
... {'a__max': 10}
Run Code Online (Sandbox Code Playgroud)
但是,我无法找到表达式的方法.尝试类似的东西:
>>> XYZ.all().aggregate(Max('x/y'))
Run Code Online (Sandbox Code Playgroud)
给出错误:
*** FieldError: Cannot resolve keyword 'x/y' into field. Choices are: a, b, x, y, id
Run Code Online (Sandbox Code Playgroud)
尝试类似的东西:
>>> XYZ.all().aggregate(Max(F('x')/F('y')))
Run Code Online (Sandbox Code Playgroud)
给出错误:
*** AttributeError: 'ExpressionNode' object has no attribute 'split'
Run Code Online (Sandbox Code Playgroud)
甚至是这样的:
XYZ.all().extra(select={'z':'x/y'}).aggregate(Max('z'))
Run Code Online (Sandbox Code Playgroud)
也不起作用,并给出与上面相同的错误:
FieldError: Cannot resolve keyword 'z' into field. Choices are: a, b, x, y, id
Run Code Online (Sandbox Code Playgroud)
我发现这样做的一个黑客是:
XYZ.all().extra(select={'z':'MAX(x/y)'})[0].z
Run Code Online (Sandbox Code Playgroud)
这实际上是有效的,因为它生成了正确的SQL,但它令人困惑,因为我确实在z atttribute获得了正确的值,但没有正确的实例,即具有该最大值的实例.
当然,我也可以使用带有extra()和order_by()的原始查询或技巧,但是我真的没理由Django以一种很好的方式支持聚合查询,但不能支持表达式甚至有自己的F表达式.
有什么办法吗?
在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;
Run Code Online (Sandbox Code Playgroud)
因此在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]
Run Code Online (Sandbox Code Playgroud)
版本
XYZ.all().extra(select={'z':'MAX(x/y)'})[0].z
Run Code Online (Sandbox Code Playgroud)
没有正确的x,y和实例,因为MAX函数在所有行之间进行求值,当没有时GROUP BY,因此返回的QuerySet中的所有实例都具有相同的zas 值MAX(x/y).