gpt4 book ai didi

Django在算术运算后聚合多列

转载 作者:行者123 更新时间:2023-12-03 19:39:59 25 4
gpt4 key购买 nike

我对 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 个域。发送的属性是尝试 - 队列。

这是我的要求:
obj = LogQuarter.objects\
.aggregate(Sum(F('attempts')-F('queue')))\
.values('domain')\
.filter(**kwargs)\
.order_by('-sent')[:20]

我也尝试过额外的,但它不起作用。

这真的是基本的 SQL,我很惊讶 Django 不能这样做。

有人有解决方案吗?

最佳答案

实际上,您可以通过对某些聚合功能进行子类化来做到这一点。这需要深入研究代码才能真正理解,但这是我为 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_query 方法。此方法决定了如何将聚合添加到基础查询对象。我们希望能够传入字段名称(例如 queue )但获得相应的数据库列名称(以防万一)。
from django.db import models
class CalculatedSum(models.Aggregate):
name = SqlCalculatedSum

def add_to_query(self, query, alias, col, source, is_summary):
# Utilize the fact that self.extra is set to all of the extra kwargs passed
# in on initialization. We want to get the corresponding database column
# name for whatever field we pass in to the "variable" kwarg.
self.extra['column'] = query.model._meta.get_field(
self.extra['variable']).db_column
query.aggregates[alias] = self.name(
col, source=source, is_summary=is_summary, **self.extra)

然后,您可以在这样的注释中使用您的新类:
queryset.annotate(calc_attempts=CalculatedSum('attempts', variable='queue'))

假设您的 attemptsqueue字段具有相同的 db 列名称,这应该生成类似于以下内容的 SQL:
SELECT SUM(`LogQuarter`.`attempts` - `LogQuarter`.`queue`) AS calc_attempts

你去吧。

关于Django在算术运算后聚合多列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13917961/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com