django Orm group by

在django 的orm里面想要group by一个模型的时候遇到一个问题,根据官方文档的调教,怎么都没办法。

1、orm model

class CvmAlarmDataByMetric(models.Model):
    """
    cvm metric类型的报警
    """
    objId = models.CharField('objId', max_length=100, help_text='objId')
    objName = models.CharField('objName', max_length=100, help_text='objName')
    alarmType = models.CharField('alarmType', max_length=20, help_text='告警类型')
    firstOccurTime = models.CharField('firstOccurTime', max_length=40, help_text='第一次告警时间')
    recoverTime = models.CharField('recoverTime', max_length=40, help_text='恢复时间')
    alarmStatus = models.CharField('alarmStatus', max_length=3, help_text='告警状态')
    metricName = models.ForeignKey(Metric, on_delete=models.CASCADE, help_text='监控项')
    durationTime = models.IntegerField('durationTime', help_text='持续时间')
    policyType = models.CharField('policyType', max_length=20, help_text='策略类型')
    policyName = models.CharField('policyName', max_length=20, help_text='策略名')
    unInstanceId = models.CharField('unInstanceId', max_length=20, help_text='实例id')
    sessionId = models.CharField('sessionId', max_length=50, help_text='会话id')
    createDate = models.DateField('创建日期', auto_now_add=True)

    def __str__(self):
        return self.objName

    class Meta:
        db_table = 'receive_CvmAlarmDataByMetric'
        ordering = ['id']
        verbose_name = 'cvm metric告警数据'
        verbose_name_plural = verbose_name

 

2、sql的实现效果就是这样

SELECT
	createDate,
	count(id) AS count
FROM
	receive_CvmAlarmDataByMetric
GROUP BY
	createDate;

3、在pycharm 的python console里面尝试,参考文档 https://docs.djangoproject.com/zh-hans/3.2/topics/db/aggregation/#order-of-annotate-and-values-clauses

from receive.models import CvmAlarmDataByMetric
from django.db.models import Count
CvmAlarmDataByMetric.objects.filter(createDate__gt="2023-01-22").values_list('createDate').annotate(counts=Count(id))
<QuerySet [(datetime.date(2023, 1, 26), 1), (datetime.date(2023, 1, 26), 1), (datetime.date(2023, 1, 24), 1), (datetime.date(2023, 1, 24), 1), (datetime.date(2023, 1, 27), 1), (datetime.date(2023, 1, 28), 1)]>

  看见这样就傻逼了,为啥跟着文档一步步操作居然没有用?

 

4、参考了这个同学的文章https://www.jianshu.com/p/9ac4ca98b8e4

q =CvmAlarmDataByMetric.objects.filter(createDate__gt="2023-01-22").values_list('createDate').annotate(counts=Count(id))
print(q.query)
SELECT `receive_CvmAlarmDataByMetric`.`createDate`, COUNT(<built-in function id>) AS `counts` FROM `receive_CvmAlarmDataByMetric` WHERE `receive_CvmAlarmDataByMetric`.`createDate` > 2023-01-22 GROUP BY `receive_CvmAlarmDataByMetric`.`id`



q =CvmAlarmDataByMetric.objects.filter(createDate__gt="2023-01-22").values_list('createDate').annotate(counts=Count(id)).order_by()
print(q.query)
SELECT `receive_CvmAlarmDataByMetric`.`createDate`, COUNT(<built-in function id>) AS `counts` FROM `receive_CvmAlarmDataByMetric` WHERE `receive_CvmAlarmDataByMetric`.`createDate` > 2023-01-22 GROUP BY `receive_CvmAlarmDataByMetric`.`createDate` ORDER BY NULL

  看看上面的两个结果,一个group by未生效,而一个生效了?参考了上面的文档后,然后我就想这么傻逼的操作官网不可能没有,然后我又去仔细的看了一下,如下链接:

https://docs.djangoproject.com/zh-hans/3.2/topics/db/aggregation/#interaction-with-order-by

原文粘贴:

The ordering by name will also play a part in the grouping, so this query will group by distinct (data, name) pairs, which isn't what you want. Instead, you should construct this queryset:

items.values('data').annotate(Count('id')).order_by()

  

所以这个就可以解释了,在模型了默认按照id进行了排序,所以就出现了想不到的后果。

 

posted @ 2023-01-29 16:18  腐汝  阅读(297)  评论(0编辑  收藏  举报