0

我定义了以下三个表。

class Operator(models.Model):
    DisplayName = models.CharField(max_length=64)

    class Meta:
        app_label = "Experiment"
        db_table = "EXPERIMENT_OPERATOR"

class OperatorSummary(models.Model):
    Operator = models.ForeignKey(Operator, related_name="TransactionSummary")
    TransactionCount = models.IntegerField()
    TransactionValue = models.DecimalField(max_digits=18, decimal_places=2)
    StartTime = models.DateTimeField(default=timezone.now())

    class Meta:
        app_label = "Experiment"
        db_table = "EXPERIMENT_OPERATORSUMMARY"

class OperatorAlerts(models.Model):
    Operator = models.ForeignKey(Operator, related_name="AlertSummary")
    AlertScore = models.IntegerField()
    AlertCount = models.IntegerField()
    StartTime = models.DateTimeField(default=timezone.now())

    class Meta:
        app_label = "Experiment"
        db_table = "EXPERIMENT_OPERATORALERTS"

对于Operator,我想检索给定日期范围的AlertScore和。TransactionCount我正在使用的查询如下所示:

tz = timezone.get_default_timezone()    
vs = Operator.objects.filter(DisplayName="Jimmy",
                             TransactionSummary__StartTime__gte=tz.localize(datetime(year=2013, month=10, day=1)),
                             AlertSummary__StartTime__gte=tz.localize(datetime(year=2013, month=10, day=1)))\
    .annotate(TotalTransactions=Sum("TransactionSummary__TransactionCount"),
              TotalAlerts=Sum("AlertSummary__AlertScore"))\
    .values("DisplayName", "TransactionSummary__TransactionCount", "AlertSummary__AlertScore")

此查询执行笛卡尔积并返回OperatorAlertsOperatorSummary表中与查询匹配的所有行。这是它返回的内容:

{'AlertSummary__AlertScore': 20, 'DisplayName': u'Jimmy', 'TransactionSummary__TransactionCount': 10}
{'AlertSummary__AlertScore': 44, 'DisplayName': u'Jimmy', 'TransactionSummary__TransactionCount': 10}
{'AlertSummary__AlertScore': 543, 'DisplayName': u'Jimmy', 'TransactionSummary__TransactionCount': 10}
{'AlertSummary__AlertScore': 20, 'DisplayName': u'Jimmy', 'TransactionSummary__TransactionCount': 22}
{'AlertSummary__AlertScore': 44, 'DisplayName': u'Jimmy', 'TransactionSummary__TransactionCount': 22}
{'AlertSummary__AlertScore': 543, 'DisplayName': u'Jimmy', 'TransactionSummary__TransactionCount': 22}
{'AlertSummary__AlertScore': 20, 'DisplayName': u'Jimmy', 'TransactionSummary__TransactionCount': 234}
{'AlertSummary__AlertScore': 44, 'DisplayName': u'Jimmy', 'TransactionSummary__TransactionCount': 234}
{'AlertSummary__AlertScore': 543, 'DisplayName': u'Jimmy', 'TransactionSummary__TransactionCount': 234}

我想解决这个问题,以便得到以下结果:

{'AlertSummary__AlertScore': 607, 'DisplayName': u'Jimmy', 'TransactionSummary__TransactionCount': 266}

所有结果都折叠成一行,其中AlertScoreTransactionCount相加。

那可能吗?我总是可以回退到对 进行单独查询,OperatorAlerts然后OperatorSummary在 Python 中迭代结果集以获得我想要或调用的结果.aggregate,但我确定一定有更好的方法吗?

4

1 回答 1

1

values()尝试颠倒应用和annotate()方法的顺序。values()应该是第一位的:

vs = Operator.objects.filter(DisplayName="Jimmy",
                             TransactionSummary__StartTime__gte=tz.localize(datetime(year=2013, month=10, day=1)),
                             AlertSummary__StartTime__gte=tz.localize(datetime(year=2013, month=10, day=1)))\
    .values("DisplayName")\
    .annotate(TotalTransactions=Sum("TransactionSummary__TransactionCount"),
              TotalAlerts=Sum("AlertSummary__AlertScore"))

这将按中提到的字段对结果进行分组values(),然后为每个组生成一个注释。订单非常重要 -如文件所述

应用values()annotate()以你做的方式(即annotate()之前values())将分别为每个项目生成注释。

请注意,上面的代码将结果分组DisplayName。您可能希望按不同的字段进行分组,例如pk

此外,我假设在您的真实代码中,您将希望一次获取多个运算符的值。如果您总是一次查询一个运算符(就像您在示例中所做的那样),您最好使用aggregate()而不是annotate().

于 2013-10-07T09:20:28.567 回答