让我们说我有一个非常简单的模型,如下所示:
class Test(models.Model):
category = models.CharField(unique=True)
start_time = models.DateTimeField()
end_time = models.DateTimeField()
基本上,我想使用Django的ORM API来获得每个类别的平均持续时间. SQL查询看起来像这样:
SELECT category, AVG(end_time - start_time) AS avg_duration
FROM test_table
GROUP BY category
我尝试使用以下代码,但根据文档,.annotate()中的F()表达式仅在Djano 1.8中可用.
Test.objects.values('category', 'start_time', 'end_time').annotate(avg_duration=Avg(F(end_time) - F(start_time))
我也试过像这样使用.extra(),但是我得到了一个FieldError.
Test.objects.extra(select={'duration':'end_time - start_time'}).values('category', 'duration').annotate(avg_duration=Avg('duration'))
从事物的外观来看,第二次尝试表明注释函数无法解析列别名.这是真的吗,还是我错过了什么?
此外,如果没有创建一个额外的列来存储派生信息(每个条目的持续时间),使用Django 1.8和/或使用原始SQL,你们还可以推荐其他什么选择?非常感谢任何帮助.谢谢!
最佳答案 试试这个:
Test.objects.values('category').extra(select={'avg_duration':'AVG(end_time - start_time)'})
是的,它不会发生,因为
Any extra() call made after a values() call will have its extra selected fields ignored.
你也不能在.values()之前使用它,因为你将被迫将它包含在.values()中:
If you use a values() clause after an extra() call, any fields defined by a select argument in the extra() must be explicitly included in the values() call.
所以这样任何.extra选择都将被包含在in the grouping中.
但是你不能在没有.extra的情况下制作这样的Avg,所以我认为唯一的解决方案就是使用.raw
Test.objects.raw('\
SELECT id, category, AVG(end_time - start_time) AS avg_duration \
FROM test_table \
GROUP BY category'
)