在Django中的ValuesQuerySet上使用extra()

jnn*_*nns 8 sql django django-queryset extra

我正在尝试用两个本身聚合的值来计算百分比.解释我所追求的SQL查询如下:

SELECT (SUM(field_a) / SUM(field_b) * 100) AS percent
FROM myapp_mymodel 
GROUP BY id
ORDER BY id
Run Code Online (Sandbox Code Playgroud)

我尝试使用以下内容来构造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'})
Run Code Online (Sandbox Code Playgroud)

令我恼火的是 - 根据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

hyn*_*cer 4

自 Django 1.8 起,聚合表达式就可以轻松地在聚合函数上使用此类表达式,而无需使用有问题的“extra()”方法。

qs = (
    MyModel.objects.values('id')
    .annotate(percent=Sum('field__a') / Sum('field__b') * 100)
    .order_by('id')
)
Run Code Online (Sandbox Code Playgroud)
>>> 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
Run Code Online (Sandbox Code Playgroud)

(提到的问题 #15546 很快就被文档注释​​关闭了,values() 之后的 extra() 将不起作用 -提交 a4a250a。)