所需的 SQL 如下所示:
SELECT *
FROM STUDENT
WHERE marks = (SELECT MAX(marks) FROM STUDENT)
要通过 Django 执行此操作,您可以使用 aggregation API。
max_marks = Student.objects.filter(
subject='Maths'
).aggregate(maxmarks=Max('marks'))['maxmarks']
Student.objects.filter(subject='Maths', marks=max_marks)
不幸的是,这个查询实际上是两个查询。执行最大标记聚合,将结果拉入 python,然后传递给第二个查询。 (令人惊讶的是)没有办法传递一个查询集,它只是一个没有分组的聚合,即使它应该是可能的。我要开一张票,看看如何解决这个问题。
编辑:
可以通过单个查询来做到这一点,但这不是很明显。我在其他地方没见过这种方法。
from django.db.models import Value
max_marks = (
Student.objects
.filter(subject='Maths')
.annotate(common=Value(1))
.values('common')
.annotate(max_marks=Max('marks'))
.values('max_marks')
)
Student.objects.filter(subject='Maths', marks=max_marks)
如果你在 shell 中打印这个查询,你会得到:
SELECT
"scratch_student"."id",
"scratch_student"."name",
"scratch_student"."subject",
"scratch_student"."marks"
FROM "scratch_student"
WHERE (
"scratch_student"."subject" = Maths
AND "scratch_student"."marks" = (
SELECT
MAX(U0."marks") AS "max_marks"
FROM "scratch_student" U0
WHERE U0."subject" = Maths))
在 Django 1.11 上测试(目前处于 alpha 阶段)。这是通过按常数 1 对注释进行分组来实现的,每一行都将分组。然后我们从选择列表中删除这个分组列(第二个values()。Django(现在)知道足以确定分组是多余的,并消除它。留下一个带有我们需要的确切 SQL 的查询。