2011-08-11 55 views
7

¿Hay alguna manera fácil de filtrar una consulta de Django en función de qué registro tiene un valor máximo/mínimo en una columna? Básicamente estoy preguntando thesequestions, pero en el contexto específico del ORM de Django.Filtrando la consulta de Django por el registro con el valor de columna máximo

p. Ej.

Supongamos que tengo un modelo diseñado para almacenar los valores históricos de los números de todos los teléfonos.

class Person(models.Model): 
    name = models.CharField(max_length=100) 
    phone = models.CharField(max_length=100) 
    created = models.DateTimeField(auto_now_add=True) 

con los registros:

Person(name='Jim',phone='123-456-9870', created=datetime(2005,1,2,4,2)) 
Person(name='Jim',phone='329-802-9870', created=datetime(2006,9,2,7,8)) 
Person(name='Sue',phone='324-345-3450', created=datetime(2008,7,4,6,1)) 

Ahora dicen que quería encontrar el número de teléfono más reciente de todos.

En SQL, yo normalmente tienen que utilizar una subconsulta para calcular los valores máximos:

SELECT p1.name, p1.phone, p1.created 
FROM person_person p1, (
    SELECT name, MAX(created) AS max_created 
    FROM person_person 
    GROUP BY name 
) AS p2 
WHERE p1.name = p2.name AND p1.created = p2.max_created 

¿Existe algún mecanismo de Django que podrían simplificar esto?

Estoy utilizando PostgreSQL en mi back-end, por lo que cualquier idea o solución que dependa de la funcionalidad específica de PostgreSQL sería útil.

+0

Parece que en django no puede hacer lo que está buscando a menos que use una consulta cruda sql. compruebe [esto] (https://docs.djangoproject.com/en/dev/ref/models/querysets/#distinct). Dado que en el momento en que agrega un order_by ('created') que se ha agregado a la selección en la consulta, el distinct no hará nada. – Hassek

Respuesta

4

Probablemente solo quiera usar SQL sin formato aquí, el método del administrador raw() lo facilita, lo que le permite devolver instancias de modelos de su consulta. El único truco es que la consulta sin formato debe incluir la clave principal. Esto probablemente se debe trabajar para usted (a menos que tenga la principal llave en algo que no sea id):

latest_phone_numbers = Person.objects.raw(''' 
SELECT p1.id, p1.name, p1.phone, p1.created 
FROM person_person p1, (
    SELECT name, MAX(created) AS max_created 
    FROM person_person 
    GROUP BY name 
) AS p2 
WHERE p1.name = p2.name AND p1.created = p2.max_created 
''') 
1

Si su base de PostgreSQL es Roman Pekar dio una buena respuesta para this cuestión.

Cuestiones relacionadas