所以我正在尝试聚合考试数据,因为数据库存在于另一台服务器上,我试图将其减少到尽可能少的数据库调用。
我有这个模型(如果重要的话,其对应的表位于mySQL数据库中):
class Exam(models.Model):
submitted = models.BooleanField(default=False)
score = models.DecimalField(default=Decimal(0))
这个查询:
>>> exam_models.Exam.objects\
... .using("exam_datebase")\
... .aggregate(average=Avg("score"),
... total=Count("submitted"))
{'average': 22.251082, 'total': 231}
我正在寻找的是一种方法来检索通过的考试数量,其中包括以下内容:
>>> exam_models.Exam.objects\
... .using("exam_datebase")\
... .aggregate(average=Avg("score"),
... total=Count("submitted"))
... passed=Count("score__gte=80"))
{'average': 22.251082, 'total': 231, 'passed': 42}
我知道我可以使用.filter(score__gte=80).count()
发送另一个查询,但我真的希望在同一聚合上获得总计数和传递计数。有什么想法吗?
答案 0 :(得分:1)
您要么需要两个查询,要么手动进行聚合。
要了解原因,让我们考虑Django生成并用于查询数据库的基础SQL。
Exam.objects.aggregate(average=Avg("score"), total=Count("submitted"))
大致翻译为
SELECT AVG(score), COUNT(submitted)
FROM exam
聚合的“Count”部分应用于底层sql查询中的SELECT子句。但是,如果我们只想包含大于某个值的分数,则SQL查询需要看起来像这样:
SELECT AVG(score), COUNT(submitted)
FROM exam
WHERE score > 80
使用特定“得分”过滤考试适用于基础SQL语句的WHERE或HAVING子句。
不幸的是,没有办法将这两件事结合起来。所以,你被困在做两个查询。
说了这么多,如果你真的想做一个查询,一个选项就是在你的python代码中进行聚合:
exams = Exam.objects.all()
total_score = 0
total_submitted = 0
passed = 0
for exam in exams:
total_score += exam.score
if exam.submitted:
total_submitted += 1
if exam.score >= 80:
passed += 1
exam_aggregates = {
'average': total_score / len(exams),
'submitted': total_submitted,
'passed': passed,
}