Python Django:在注释()之后聚合到特定级别(&;值()

Python Django:在注释()之后聚合到特定级别(&;值(),python,django,aggregate,annotate,Python,Django,Aggregate,Annotate,我试图用Django将值聚合到一个特定的级别,但它似乎并不严格:聚合发生在完整的queryset或对象级别,但不是“中间” 这里是我的查询:我需要根据多个事件条目计算每年的总活动时间 events.annotate( # Extracting the year year = ExtractYear('dtstart') ).annotate( # Computing duration...

我试图用Django将值聚合到一个特定的级别,但它似乎并不严格:聚合发生在完整的queryset或对象级别,但不是“中间”

这里是我的查询:我需要根据多个事件条目计算每年的总活动时间

events.annotate(                      # Extracting the year
       year = ExtractYear('dtstart')
   ).annotate(                        # Computing duration... 
       time_span= ExpressionWrapper(
               F('dtend') - F('dtstart'), 
               output_field=IntegerField()
           )
   ).values(                          # ... then aggregating by year
       'year', 'time_span'             #!!!! ... BUT ALSO unfortunately
                                      # by 'time_span' !!!!!!!!!!!!!!!
   ).annotate(                        # otherwise 'time_span' would not
       total_span=Sum('time_span')    # be available for a new computation.
   ).values(                          # Therefore, the result is not
       'year', 'total_span'           # grouped by year, but by the
   ).order_by(                        # distinct combination of 'year'
       'year'                         # AND 'total_span'
   )
因此,我得到以下结果:

<QuerySet [
{'total_span': 1800000000, 'year': 2016}, 
{'total_span': 7200000000, 'year': 2016}, 
{'total_span': 2700000000, 'year': 2016}, 
{'total_span': 14400000000, 'year': 2016}, 
{'total_span': 8100000000, 'year': 2017}, ...>

而不是像这样:

<QuerySet [
{'total_span': 16700000000, 'year': 2016}, 
{'total_span': 19800000000, 'year': 2017}, ...>

为了设置聚合级别,我需要如下内容:

合计(总计=总和(“时间”),按年度分组


我想我应该转向子查询或自定义聚合类,但这超出了我目前的技能范围。如果您有任何提示,我们将不胜感激……

我想这可能是您将回到基础并编写一些SQL的情况之一。ORMs很好,但有时尝试使用它比默认返回到工作状态要困难得多。您可能可以让它与ORM一起工作,但这可能要容易得多

from django.db import connection

cursor = connection.cursor()
cursor.execute("""
    select
      sum(dtend - dtstart) as total,
      DATE_FORMAT(dtstart, "%Y") as year
    from events
    group by year;""")

for row in cursor.fetchall():
    # Do something with it
编辑:一如既往,确保清理您可能通过原始SQL输入的任何用户输入