Фильтрация запроса Django по записи с максимальным значением столбца - PullRequest
8 голосов
/ 11 августа 2011

Есть ли простой способ отфильтровать запрос Django на основе того, какая запись имеет максимальное / минимальное значение в столбце?По сути, я задаю эти вопросы , но в конкретном контексте ORM Джанго.

например,

Скажем, у меня есть модель, предназначенная для храненияисторические значения телефонных номеров каждого.

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

с записями:

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))

Теперь скажите, что я хотел найти самый последний номер телефона каждого.

В SQLОбычно мне нужно использовать подзапрос для вычисления максимальных значений:

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

Есть ли какой-нибудь механизм в Django, который мог бы упростить это?

Я использую PostgreSQL на своем бэкэндепоэтому любые мысли или решения, которые будут опираться на специальные функции PostgreSQL, будут полезны.

Ответы [ 2 ]

4 голосов
/ 11 августа 2011

Вы, вероятно, просто захотите использовать сырой SQL здесь, метод менеджера raw() облегчает это, позволяя вам возвращать экземпляры модели из вашего запроса. Единственная хитрость в том, что необработанный запрос должен включать первичный ключ. Это, вероятно, должно работать для вас (если у вас не установлен первичный ключ, отличный от 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 голос
/ 12 сентября 2013

Если ваш бэкэнд - PostgreSQL Роман Пекар дал хороший ответ на этот вопрос.

...