Django查询具有聚合和不分组的计算字段的表达式

时间:2016-01-12 21:58:37

标签: python django django-orm

继续here

我在Django中有以下查询表达式:

Connection.prototype.query = function query(sql, values, cb) {
  var query = Connection.createQuery(sql, values, cb);
  query._connection = this;

  if (!(typeof sql == 'object' && 'typeCast' in sql)) {
    query.typeCast = this.config.typeCast;
  }

  if (query.sql) {
    query.sql = this.format(query.sql, query.values);
  }

  this._implyConnect();

  return this._protocol._enqueue(query);
};

这可以正确计算按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) 分组的汇总字段impressionsclicksctr,并生成以下postgres查询:

product

现在我想要的是修改这个表达式,这样当没有提供分组时,它只会在整个表中返回聚合值。

它似乎比我预期的更难。问题的其余部分可以跳过,我只是列出我尝试过的内容。

1)首先尝试放弃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";

values()

这会产生错误:

Stats.objects.annotate(**fields).annotate(**calc_fields)

这可能是因为它现在尝试返回包含其所有字段的完整The annotation 'impressions' conflicts with a field on the model. 对象的列表,而不是仅返回我之前列出的自定义字段。也许有一种方法可以禁用它并返回自定义字段?

我尝试重命名字段,但它会导致主索引分组,因此它返回表中的所有记录而不是一个

2)也许我需要将注释与聚合交换。

Stats

这会产生错误:

Stats.objects.aggregate(**fields).aggregate(**calc_fields)

好吧也许他们无法链接,让我们将这些字段合并在一起,并在案例中与Error: 'dict' object has no attribute 'aggregate' 交换F

Sum

这似乎工作正常。但是当我添加额外的字段时,地狱再次破裂(所有值都相同,只有名称不同):

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)

似乎问题是由多个fields = { 'impressions': models.Sum('impressions'), 'impressions2': models.Sum('impressions'), 'clicks': models.Sum('clicks'), 'clicks2': 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()), 'ctr2': models.Case(models.When(impressions = 0, then = 0), default = 1.0 * models.Sum('clicks') / models.Sum('impressions'), output_field = models.FloatField()), } 引起的,它会生成错误的sql:

models.When(impressions = 0)

请注意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"; 的CASE如何被错误地计算为:

ctr

虽然CASE WHEN "stats"."impressions" = 0 是正确的:

ctr2

导致数据库错误:

CASE WHEN SUM("stats"."impressions") = 0

3)将所有聚合字段重命名为与模型字段不同,这样就不会产生混淆:

column "stats.impressions" must appear in the GROUP BY clause or be used in an aggregate function

这会产生错误:

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,它就可以了。再次添加额外字段会因某种原因而中断。

任何提示?我希望它只返回一个自定义字段数组而不是完整对象。

0 个答案:

没有答案