如何统计Django中每家企业拥有超1个客户的员工数量?
解决Django中统计企业内客户数超1的员工数量问题
嗨,我来帮你搞定这个统计需求!首先咱们先确认下模型的关联结构(如果你的实际字段名有差异,调整对应名称即可):
class Business(models.Model): name = models.CharField(max_length=100) # 其他自定义字段... class Employee(models.Model): business = models.ForeignKey(Business, on_delete=models.CASCADE, related_name='employees') name = models.CharField(max_length=100) # 其他自定义字段... class Client(models.Model): employee = models.ForeignKey(Employee, on_delete=models.CASCADE, related_name='clients') name = models.CharField(max_length=100) # 其他自定义字段...
你之前尝试用Count结合Subquery没得到预期结果,大概率是子查询的逻辑没处理对——咱们需要先筛选出客户数超过1的员工,再统计每个企业下这类员工的数量,而不是直接统计客户数。
正确实现方式:用Subquery统计符合条件的员工数
咱们可以分两步构建查询:
- 先写子查询:针对当前企业(用
OuterRef关联外层的Business),给每个员工标注客户数,筛选出客户数>1的员工,最后统计这些员工的总数。 - 在外层的
Business查询中,用这个子查询来标注每个企业对应的目标员工数量。
具体代码如下:
from django.db.models import Count, Subquery, OuterRef, IntegerField # 构建子查询:统计单个企业下客户数>1的员工数量 qualified_employees_subquery = Employee.objects.filter( business=OuterRef('pk') # 关联外层的Business对象 ).annotate( client_count=Count('clients') # 统计每个员工的客户数 ).filter( client_count__gt=1 # 筛选出客户数超过1的员工 ).values('business').annotate( count=Count('id') # 统计符合条件的员工总数 ).values('count') # 只提取统计数值 # 对Business进行标注,获取最终结果 businesses_with_stats = Business.objects.annotate( employees_with_more_than_one_client=Subquery( qualified_employees_subquery, output_field=IntegerField() # 指定返回字段类型 ) )
验证结果
现在你可以遍历businesses_with_stats,每个Business对象都会有employees_with_more_than_one_client属性,直接获取数值即可:
for business in businesses_with_stats: print(f"{business.name}: {business.employees_with_more_than_one_client}名员工有超过1个客户")
另一种简化方式:用FilteredRelation(Django 2.0+)
如果你用的是Django 2.0及以上版本,也可以用FilteredRelation来过滤关联的员工,再统计数量:
from django.db.models import FilteredRelation, Q businesses_with_stats = Business.objects.annotate( # 过滤出当前企业下客户数>1的员工 qualified_employees=FilteredRelation( 'employees', condition=Q(employees__clients__count__gt=1) ) ).annotate( # 统计过滤后的员工数量,注意加distinct避免重复计数 employees_with_more_than_one_client=Count('qualified_employees', distinct=True) )
这种方式更简洁,但要注意加上distinct=True,避免因为员工有多个客户导致重复统计。
内容的提问来源于stack exchange,提问作者Amir Shabani
相关产品推荐
相关产品推荐

