Python 计算字段的Django查询表达式,带聚合,不带分组
继续从 我在Django中有以下查询表达式:Python 计算字段的Django查询表达式,带聚合,不带分组,python,django,django-orm,Python,Django,Django Orm,继续从 我在Django中有以下查询表达式: fields = { 'impressions': models.Sum('impressions'), 'clicks': models.Sum('clicks'), } calc_fields = { 'ctr': models.Case(models.When(impressions = 0, then = 0), default = 1.0 * models.F('clicks') / models.F('impr
fields = {
'impressions': models.Sum('impressions'),
'clicks': models.Sum('clicks'),
}
calc_fields = {
'ctr': models.Case(models.When(impressions = 0, then = 0), default = 1.0 * models.F('clicks') / models.F('impressions'), output_field = models.FloatField()),
}
Stats.objects.values('product').annotate(**fields).annotate(**calc_fields)
这将正确计算聚合字段印象
,单击
和按产品
分组的ctr
,并生成以下postgres查询:
SELECT
"stats"."product_id",
SUM("stats"."impressions") AS "impressions",
SUM("stats"."clicks") AS "clicks",
CASE WHEN SUM("stats"."impressions") = 0 THEN 0 ELSE ((1.0 * SUM("stats"."clicks")) / SUM("stats"."impressions")) END AS "ctr"
FROM "stats"
GROUP BY "stats"."product_id";
现在我只想修改这个表达式,这样当不提供分组时,它只返回整个表中的聚合值。
看起来比我想象的要难。问题的其余部分可以跳过,我只是列出我尝试过的内容
1) 第一次尝试删除值()
:
这会产生一个错误:
The annotation 'impressions' conflicts with a field on the model.
Error: 'dict' object has no attribute 'aggregate'
这可能是因为它现在尝试返回一个包含所有字段的完整Stats
对象列表,而不是像以前一样只返回自定义字段。也许有办法禁用它,只返回自定义字段
我尝试重命名字段,但结果是按主索引分组,因此它返回表中的所有记录,而不是一条记录
2) 也许我需要用聚合替换注释
Stats.objects.aggregate(**fields).aggregate(**calc_fields)
这会产生一个错误:
The annotation 'impressions' conflicts with a field on the model.
Error: 'dict' object has no attribute 'aggregate'
好的,也许它们无法链接,让我们将字段合并在一起,并在案例中用Sum
交换F
:
fields = {
'impressions': models.Sum('impressions'),
'clicks': models.Sum('clicks'),
'ctr': models.Case(models.When(impressions = 0, then = 0), default = 1.0 * models.Sum('clicks') / models.Sum('impressions'), output_field = models.FloatField()),
}
Stats.objects.aggregate(**fields)
这似乎工作正常。但当我添加额外的字段时(所有值都是相同的,只是名称不同),地狱再次爆发:
问题似乎是由多个模型引起的。当(impressions=0)
时,它会生成错误的sql:
SELECT
CASE WHEN "stats"."impressions" = 0 THEN 0 ELSE ((1.0 * SUM("stats"."clicks")) / SUM("stats"."impressions")) END AS "ctr",
CASE WHEN SUM("fstats"."impressions") = 0 THEN 0 ELSE ((1.0 * SUM("stats"."clicks")) / SUM("impressions")) END AS "ctr2",
SUM("stats"."impressions") AS "impressions",
SUM("stats"."impressions") AS "impressions2",
SUM("stats"."clicks") AS "clicks",
SUM("stats"."clicks") AS "clicks2",
FROM "stats";
请注意,ctr
的情况如何被错误地计算为:
CASE WHEN "stats"."impressions" = 0
对于ctr2
而言,这是正确的:
CASE WHEN SUM("stats"."impressions") = 0
这会导致数据库错误:
column "stats.impressions" must appear in the GROUP BY clause or be used in an aggregate function
3) 将所有聚合字段重命名为不同于模型字段,以避免混淆:
fields = {
'impressions_total': models.Sum('impressions'),
'impressions_total2': models.Sum('impressions'),
'clicks_total': models.Sum('clicks'),
'clicks_total2': models.Sum('clicks'),
'ctr': models.Case(models.When(impressions_total = 0, then = 0), default = 1.0 * models.Sum('clicks') / models.Sum('impressions'), output_field = models.FloatField()),
'ctr2': models.Case(models.When(impressions_total = 0, then = 0), default = 1.0 * models.Sum('clicks') / models.Sum('impressions'), output_field = models.FloatField()),
}
Stats.objects.aggregate(**fields)
这会产生错误:
Error: Cannot resolve keyword 'impressions_total' into field. Choices are: clicks, clicks_total, impressions, impressions_total2, product, product_id
如果我离开单ctr
而没有ctr2
它工作正常。由于某种原因,再次添加额外字段会破坏它
有什么建议吗?我希望它只返回一个自定义字段数组,而不是完整的对象。我跳过了问题的其余部分。我的印象是,
impressions
字段是模型/记录的一部分,因此与注释冲突,正如您所指出的。如果是这样,您是否尝试过将注释字段的名称更改为其他名称?e、 g.fields={'imprex':models.Sum('impressions'),..
@Pynchia要与aggregate()
一起使用?如果尝试了它,它会产生一个django错误(我在“3”下列出了结果)@Pynchia如果与annotate()
一起使用,它会附加group by stats.id
(主索引)在这种情况下,您是否尝试过Stats.objects.annotate(**fields).aggregate(**calc_fields)
?@Pynchia仍然按主id分组