2015-10-16 113 views
0

您想提取一段时间内有关重复的呼叫统计。Django queryset多个聚合

实施例:

class Call(models.Model): 
    when_start = models.DateTimeField() 
    when_end = models.DateTimeField() 
    caller = models.CharField() 
    dnis = models.CharField() 

我应该得到这样的:

result = {4: 1, 3: 3, 2: 4, 1: 1} 

详情:

  • 4:1 => 1人称为4次
  • 3:3 = > 3人叫3次
  • 2:4 => 4人称为2倍
  • 1:称为1 => 1人1次

我试图与此查询集,但我由呼叫者获得结果:

Call.objects.filter(when_start__range=(dt_start, dt_end)).values('caller').annotate(caller_count=Count('caller')).order_by('-caller_count') 

[{'caller_count': 4, 'caller': u'Mr X'}, 
{'caller_count': 3, 'caller': u'Mr Y'}, 
{'caller_count': 3, 'caller': u'Mr T'}, 
{'caller_count': 3, 'caller': u'Mr E'}, 
{'caller_count': 2, 'caller': u'Mr O'}, 
{'caller_count': 2, 'caller': u'Mr M'}, 
{'caller_count': 2, 'caller': u'Mr P'}, 
{'caller_count': 2, 'caller': u'Mr B'}, 
{'caller_count': 1, 'caller': u'Mr N'}] 

所以我必须添加此代码以获得结果:

result = {} 

for data in calls: 
    if data['caller_count'] not in result: 
     result[data['caller_count']] = 1 
    else: 
     result[data['caller_count']] += 1 

是否有可能直接使用一个查询集获得此结果?

+0

我不认为这是可能的,但你可以使用'defaultdict(INT)'来简化你的for循环。它不会那么糟糕,因为理想情况下,聚合结果的数量远小于原始对象数量。 –

回答

0

你试过下一步:

Call.objects.filter(when_start__range=(dt_start, dt_end)) 
      .values('caller').annotate(caller_count=Count('caller')) 
      .order_by('-caller_count').annotate(Count('caller_count')) 
+0

是的:'FieldError:无法计算Count('caller_count'):'caller_count'是一个聚合 –