You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Django ORM高效计算各车型占比(单查询实现)

Django ORM 单查询实现车型分组占比计算

问题原因

你的代码中,第一个annotate(total=Count('pk'))在执行values('car_type_name')后,total会被重新计算为当前分组内的记录数,而非全局总车辆数。这就导致每组的car_type_count和total数值相等,最终占比全部为100%。

解决方案

以下两种方案均为单查询实现,避免迭代式计算带来的性能损耗:

方案1:使用Subquery获取全局总数量

from django.db.models import Subquery, OuterRef, Count, FloatField, F, Cast

def calculate_car_type_ratio(cars_queryset):
    # 子查询获取当前QuerySet的总车辆数
    total_subquery = cars_queryset.values('pk').annotate(total=Count('pk')).values('total')
    
    result = cars_queryset.values('car_type__name')\
        .annotate(
            this_car_type_count=Count('id'),
            total=Subquery(total_subquery[:1])
        )\
        .annotate(
            percentage=Cast(F('this_car_type_count') * 100.0 / F('total'), FloatField())
        )\
        .values(
            car_type=F('car_type__name'),
            percentage=F('percentage'),
            this_car_type_count=F('this_car_type_count')
        )
    return list(result)
  • 原理:通过子查询提前计算输入QuerySet的全局总车辆数,分组时直接引用该值,避免分组后重新计算total。
  • 兼容性:支持所有Django版本,适合老项目使用。

方案2:使用Window函数(Django 2.0+)

from django.db.models import Window, Count, FloatField, F, Cast

def calculate_car_type_ratio(cars_queryset):
    result = cars_queryset.annotate(
        # 使用Window函数计算全局总车辆数
        total=Window(expression=Count('id'))
    )\
    .values('car_type__name')\
    .annotate(
        this_car_type_count=Count('id'),
        percentage=Cast(F('this_car_type_count') * 100.0 / F('total'), FloatField())
    )\
    .values(
        car_type=F('car_type__name'),
        percentage=F('percentage'),
        this_car_type_count=F('this_car_type_count')
    )\
    .distinct()  # 去重,消除Window函数带来的重复分组记录
    
    return list(result)
  • 原理:Window函数允许在不分组的前提下计算全局聚合值,后续分组时直接使用该值计算占比。
  • 优势:代码更简洁,可读性更强,适合使用Django 2.0及以上版本的项目。

输出示例

调用上述函数后,会返回符合要求的字典列表:

[
    {'car_type': 'car01', 'percentage': 70.0, 'this_car_type_count': 20},
    {'car_type': 'car02', 'percentage': 30.0, 'this_car_type_count': 9},
    ...
]

内容的提问来源于stack exchange,提问作者Muhammad Hammad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 00:15:39