【问题标题】:Django 1.6 + MySQL : Type Cast MySQL variable to search for Max, AvgDjango 1.6 + MySQL:键入 Cast MySQL 变量以搜索 Max、Avg
【发布时间】:2015-05-17 03:21:53
【问题描述】:

我的模型有点像

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 中的值,w.r.t 存储为 unixtime 的时间

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

我试过了:

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_utilizationstatus.sys_timestamp DESC;

但是工作代码需要一个 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_utilizationstatus.device_name, performance_utilizationstatus.service_name, performance_utilizationstatus.data_source 通过performance_utilizationstatus.sys_timestamp DESC 订购;

如何添加 GROUP BY CLAUSE ?

在这里使用annotate 不起作用

1111, 'Invalid use of group function'

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

RAW SQL 会是最后的手段吗?

【问题讨论】:

    标签: mysql django django-orm django-aggregation


    【解决方案1】:

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

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

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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-15
      • 2010-10-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多