El SQL requerido sería algo como esto:
SELECT *
FROM STUDENT
WHERE marks = (SELECT MAX(marks) FROM STUDENT)
hacerlo a través de Django, puede utilizar la aggregation API.
max_marks = Student.objects.filter(
subject='Maths'
).aggregate(maxmarks=Max('marks'))['maxmarks']
Student.objects.filter(subject='Maths', marks=max_marks)
Lamentablemente, esta consulta es en realidad dos consultas. Se ejecuta la agregación de marca máxima, el resultado se extrae en python y luego se pasa a la segunda consulta. No hay forma (sorprendentemente) de pasar un conjunto de consulta que sea simplemente una agregación sin una agrupación, aunque debería ser posible hacerlo. Voy a abrir un ticket para ver cómo se puede solucionar.
Editar:
Se es posible hacer esto con una sola consulta, pero no es muy obvio. No he visto este método en otro lado.
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)
Si imprime esta consulta en la cáscara que se obtiene:
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))
probado en Django 1.11 (actualmente en alfa). Esto funciona agrupando la anotación por la constante 1, en la que se agruparán todas las filas. Luego eliminamos esta columna de agrupación de la lista de selección (la segunda values()
. Django (ahora) sabe lo suficiente como para determinar que la agrupación es redundante y la elimina. Dejando una sola consulta con el SQL exacto que necesitamos.
¿Cuál es el F en F ('max_mark')? –
@ChadVernon, se llaman expresiones F(). Le permiten usar el valor de otra columna. https://docs.djangoproject.com/en/dev/topics/db/queries/#query-expressions –
Esto no funciona. El SQL resultante es algo así como: 'SELECT *, MAX (" mark ") AS" max_mark "FROM STUDENT QUE TIENE" STUDENT "." Mark "= (MAX (" STUDENT "." Marks "))', que simplemente selecciona todo estudiantes. –