我的模型有点像
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的浮点值,w.r.t存储为unixtime的时间
在尝试获取current_value
的Max和Average值时,我得到了意想不到的结果,因为对于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`
FROM performance_utilizationstatus
ORDER BY performance_utilizationstatus
。sys_timestamp
DESC;
但是工作代码需要GROUP BY(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`
GROUP BY performance_utilizationstatus
。device_name
,performance_utilizationstatus
。service_name
,
performance_utilizationstatus
。data_source
ORDER BY 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会不会成为最后的手段?
答案 0 :(得分:0)
我认为你必须使用.raw
,因为在这里使用.extra
是不可能的。
问题是因为Django
没有.group_by
唯一的方法是在此之后使用.values
和.annotate
。 (,因为你在第一次尝试时已经完成了)
所以..为什么你不能使用.extra
?这是因为:
在values()调用之后进行的任何extra()调用都会有额外的 选中的字段被忽略。
和
如果在extra()调用后使用values()子句,则定义任何字段 通过extra()中的select参数必须明确包含在 values()调用。
因此获取.extra
字段的唯一方法是将它们添加到.values
中,但这会导致按此字段进行分组,这是一种不受欢迎的行为。