Django用annotate多Sum聚合按客户国家分组统计服务器资源
实现方案
1. 预处理无主服务器关联
首先创建Unknown客户,将所有未绑定客户的服务器关联到该客户,解决customer字段为空的问题:
from .models import Customer, Server # 不存在则创建Unknown客户 unknown_customer, _ = Customer.objects.get_or_create( name="Unknown", defaults={"enabled": True} ) # 批量更新所有无主服务器的客户关联 Server.objects.filter(customer__isnull=True).update(customer=unknown_customer)
2. 多维度聚合统计
直接使用Django ORM的分组聚合能力,跨表关联取国家维度,同时统计所需的所有指标:
from django.db.models import Count, Sum, F stats = Server.objects.values( # 定义分组维度:客户、国家 customer_id=F("customer__id"), customer_name=F("customer__name"), country_id=F("city__country__id"), country_name=F("city__country__name") ).annotate( # 聚合统计指标 server_total=Count("id", distinct=True), cpu_total=Sum("cpu"), ram_total=Sum("ram"), disk_total=Sum("Disks__size") ).order_by("customer_name", "country_name")
结果说明
返回的stats是字典格式的可迭代对象,每个元素对应一个分组的统计结果,字段如下:
- customer_id、customer_name:客户维度信息,无主服务器对应名称为
Unknown - country_id、country_name:国家维度信息
- server_total:分组内服务器总数量
- cpu_total:分组内服务器CPU核数总和
- ram_total:分组内服务器内存总容量
- disk_total:分组内所有服务器挂载的磁盘总容量
注意事项
- 题目已约束所有服务器关联城市、城市关联国家,无需处理国家维度空值
- 统计服务器数量时加
distinct=True是为了避免一对多关联磁盘时,单台服务器被重复计数 - 如果需要对统计值做单位转换,可直接在annotate阶段通过F表达式计算,或遍历结果后处理
内容的提问来源于stack exchange,提问作者Fumble
相关产品推荐
相关产品推荐

