Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Django在算术运算后聚合多个列_Django_Django Models - Fatal编程技术网

Django在算术运算后聚合多个列

Django在算术运算后聚合多个列,django,django-models,Django,Django Models,我对Django 1.4.4有一个非常奇怪的问题 我有这个模型: class LogQuarter(models.Model): timestamp = models.DateTimeField() domain = models.CharField(max_length=253) attempts = models.IntegerField() success = models.IntegerField() queue = models.IntegerField() .

我对Django 1.4.4有一个非常奇怪的问题

我有这个模型:

class LogQuarter(models.Model):
  timestamp = models.DateTimeField()
  domain = models.CharField(max_length=253)
  attempts = models.IntegerField()
  success = models.IntegerField()
  queue = models.IntegerField()
  ...
我需要收集具有较高发送属性的前20个域。sent属性为尝试-队列

这是我的要求:

obj = LogQuarter.objects\
      .aggregate(Sum(F('attempts')-F('queue')))\
      .values('domain')\
      .filter(**kwargs)\
      .order_by('-sent')[:20]
我也尝试了额外的,但它不起作用

这是非常基本的SQL,我很惊讶Django不能做到这一点


有人有解决方案吗?

我不确定你是否可以这样做
Sum(F('truments')-F('queue'))
。它首先应该抛出一个错误。我想,更简单的方法是使用额外的

result = LogQuarter.objects.extra(select={'sent':'(attempts-queue)'}, order_by=['-sent'])[:20]

实际上,您可以通过将一些聚合功能子类化来实现这一点。这需要深入了解代码才能真正理解,但下面是我编写的代码,用于对
MAX
MIN
执行类似的操作。(注意:此代码基于Django 1.4/MySQL)

首先对基础聚合类进行子类化,并重写as_sql方法。此方法将实际SQL写入数据库查询。我们必须确保正确引用传入的字段,并将其与正确的表名相关联

from django.db.models.sql import aggregates
class SqlCalculatedSum(aggregates.Aggregate):
  sql_function = 'SUM'
  sql_template = '%(function)s(%(field)s - %(other_field)s)'

  def as_sql(self, qn, connection):
    # self.col is currently a tuple, where the first item is the table name and
    # the second item is the primary column name. Assuming our calculation is
    # on two fields in the same table, we can use that to our advantage. qn is
    # underlying DB quoting object and quotes things appropriately. The column
    # entry in the self.extra var is the actual database column name for the
    # secondary column.
    self.extra['other_field'] = '.'.join(
        [qn(c) for c in (self.col[0], self.extra['column'])])
    return super(SqlCalculatedSum, self).as_sql(qn, connection)
接下来,对通用模型聚合类进行子类化,并重写add_to_查询方法。此方法决定如何将聚合添加到基础查询对象。我们希望能够传入字段名(例如,
队列
),但获得相应的DB列名(以防它有所不同)

然后,您可以在如下注释中使用新类:

queryset.annotate(calc_attempts=CalculatedSum('attempts', variable='queue'))
假设您的
尝试
队列
字段具有相同的db列名,这将生成类似以下内容的SQL:

SELECT SUM(`LogQuarter`.`attempts` - `LogQuarter`.`queue`) AS calc_attempts

这就是问题所在。

此解决方案的问题在于我没有域上的分组依据。我收集了前20行,但没有汇总。非常感谢,我想那时我可以找到更简单的东西,但它完成了任务!
SELECT SUM(`LogQuarter`.`attempts` - `LogQuarter`.`queue`) AS calc_attempts