所需的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的單個查詢
什麼是F在F( 'max_mark')? – 2013-01-16 07:59:31
@ChadVernon,它們被稱爲F()表達式。它們允許您使用另一列的值。 https://docs.djangoproject.com/en/dev/topics/db/queries/#query-expressions – 2013-01-16 21:08:45
這不起作用。生成的SQL如下所示:'SELECT *,MAX(「mark」)AS「max_mark」FROM STUDENT HAVING「STUDENT」。「mark」=(MAX(「STUDENT」。「marks」))',學生們。 – 2016-11-18 19:55:06