我正在尝试使用两个本身聚合的值来计算百分比。解释我所追求的SQL查询如下:
SELECT (SUM(field_a) / SUM(field_b) * 100) AS percent
FROM myapp_mymodel
GROUP BY id
ORDER BY id
我尝试使用以下命令构造QuerySet,但不幸的是它不包含额外的字段:
MyModel.objects.values('id').annotate(
sum_field_a=Sum('field_a'),
sum_field_b=Sum('field_b')).extra(
select={'percent': 'sum_field_a / sum_field_b * 100'})
令我恼火的是 - 根据Django文档 - 这似乎是要走的路:
当使用values()子句时 约束列 在结果集中返回[...] 而不是返回 每个结果的注释结果 原始的QuerySet,原始的 结果按照分组 独特的领域组合 在values()子句中指定。一个 然后为每个提供注释 独特的群体;注释是 计算所有成员 基。
来源: http://docs.djangoproject.com/en/dev/topics/db/aggregation/#values
如果在extra()子句后使用values()子句,则extra()中的select参数定义的任何字段都必须显式包含在values()子句中。但是,如果在values()之后使用extra()子句,则select会添加的字段将自动包含在内。
来源: http://docs.djangoproject.com/en/dev/ref/models/querysets/#values
答案 0 :(得分:3)
Aggregate expressions 可以轻松地在聚合函数since Django 1.8上使用这些表达式,而不会出现问题' extra()'方法
qs = (
MyModel.objects.values('id')
.annotate(percent=Sum('field__a') / Sum('field__b') * 100)
.order_by('id')
)
>>> print(str(qs.query))
SELECT id, ((SUM(field_a) / SUM(field_b)) * 100) AS percent
FROM app_mymodel GROUP BY id ORDER BY id ASC
(上述问题#15546很快就被文件说明关闭,因为值()之后的额外()不起作用 - commit a4a250a。)
答案 1 :(得分:0)
正如您所指出的(#15546),django可能存在错误。
但作为一种解决方法,您可以通过执行以下操作将实际计算的负担放在python而不是SQL数据库上:
[{'field_c': model['field_c'],
'percent': m['sum_field_a'] * 100.0 / m['sum_field_b']}
for model in MyModel.objects.values('field_c').annotate(
sum_field_a=Sum('field_a'),
sum_field_b=Sum('field_b')).order_by('field_c')]
由于此解决方案会强制您遍历所有数据,具体取决于您要执行的操作,因此可能会或可能不会接受。
答案 2 :(得分:0)
如果在extra()子句后使用values()子句,则extra()中的select参数定义的任何字段都必须显式包含在values()子句中。
来源:http://docs.djangoproject.com/en/dev/ref/models/querysets/#values
select中添加的'percent'字段可以显式添加到values子句中,并且应该添加到查询集中。
MyModel.objects.annotate(
sum_field_a=Sum('field_a'),
sum_field_b=Sum('field_b')).extra(
select={'percent': 'sum_field_a / sum_field_b * 100'}
).values('id', 'percent')