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_valueVarChar として格納された Float の値を表し、unixtime として格納された時刻について

の最大値と平均値を取得しようとしているcurrent_valueときに、予期しない結果が得られます。これは、Max の場合、MySQL が文字列ベースの比較を行うため、'100' value < '9.99'誤った wrt 値が Float で取得されるためです。

私は試した :

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')
    )

間違った結果を提供します。

次に見てください:mysqlでキャストvarcharからintに最小値を選択する方法

クエリセットを提供することを考えました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_timestampDESC;

ただし、作業コードでは、(device_name、service_name、data_source) で GROUP BY が必要になります。

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_nameperformance_utilizationstatusservice_nameperformance_utilizationstatusdata_source オーダーバイperformance_utilizationstatussys_timestampDESC;

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 に答える