1

我的模型有点像

class ServiceUtilization(models.Model):
device_name = models.CharField()
service_name = models.CharField()
data_source = models.CharField()
current_value = models.CharField()
sys_timestamp = models.IntegerField()

现在,这里current_value表示存储为 VarChar 的 Float 中的值,以及存储为 unixtime 的时间

在尝试获取 Max 和 Average 值时,current_value我得到了意想不到的结果,因为对于 Max,MySQL 会进行基于字符串的比较,其中'100' value < '9.99'在 Float 中采用了不正确的 wrt 值。

我试过了 :

perf = ServiceUtilization.objects.filter(
        device_name__in=devices,
        service_name__in=services,
        data_source__in=data_sources,
        sys_timestamp__gte=start_date,
        sys_timestamp__lte=end_date
    ).values(
        'device_name',
        'service_name',
        'data_source'
    ).annotate(
        max_val=Max('current_value'),
        avg_val=Avg('current_value')
    )

它提供了不正确的结果。

然后看:HOW select min from cast varchar to int in mysql

我考虑过提供查询集extra

perf = ServiceUtilization.objects.extra(
       select={
          'max_val': "MAX(CAST(current_value AS SIGNED))",
          'avg_val': "AVG(CAST(current_value AS SIGNED))"
       }
       ).filter(
        device_name__in=devices,
        service_name__in=services,
        data_source__in=data_sources,
        sys_timestamp__gte=start_date,
        sys_timestamp__lte=end_date
    ).values(
        'device_name',
        'service_name',
        'data_source',
        'max_val',
        'avg_val'
    )

但这只是提供了一个单一的价值,而不是想要的结果。这转换为 SQL

SELECT (MAX(CAST(current_value AS SIGNED))) AS `max_val`, (AVG(CAST(current_value AS SIGNED))) AS `avg_val`, `performance_utilizationstatus`.`device_name`, `performance_utilizationstatus`.`service_name`, `performance_utilizationstatus`.`data_source`

performance_utilizationstatus订购performance_utilizationstatussys_timestamp降序;

但是工作代码需要一个 GROUP BY on (device_name, service_name, data_source)

SELECT (MAX(CAST(current_value AS SIGNED))) AS `max_val`, (AVG(CAST(current_value AS SIGNED))) AS `avg_val`, `performance_utilizationstatus`.`device_name`, `performance_utilizationstatus`.`service_name`, `performance_utilizationstatus`.`data_source`  FROM `performance_utilizationstatus` 

分组依据performance_utilizationstatusdevice_name, performance_utilizationstatus. service_name, performance_utilizationstatus. data_source 订购方式performance_utilizationstatussys_timestamp降序;

如何添加 GROUP BY CLAUSE ?

在这里使用annotate不起作用

1111, 'Invalid use of group function'

或者

ERROR 1056 (42000): Can't group on 'max_val'

RAW SQL 会是最后的手段吗?

4

1 回答 1

0

我认为您必须使用,.raw因为.extra在这里无法使用。

问题是因为Django没有.group_by唯一的方法去分组的东西是使用.values.annotate之后。(正如您在第一次尝试中所做的那样

所以..为什么你不能使用.extra?因为:

在 values() 调用之后进行的任何 extra() 调用都将忽略其额外的选定字段。

如果在 extra() 调用之后使用 values() 子句,则由 extra() 中的 select 参数定义的任何字段都必须显式包含在 values() 调用中。

因此获取.extra字段的唯一方法是将它们添加到其中.values,但这会导致按此字段分组,这是一种不受欢迎的行为。

于 2015-03-16T10:03:06.737 回答