Как получить значения последних записей, сгруппированных по атрибутам, используя Django ORM? - PullRequest
0 голосов
/ 09 марта 2010

У меня модель отчета выглядит примерно так:

class Report(models.Model):
    date = models.DateField()
    quantity = models.IntegerField()
    product_name = models.TextField()

Я знаю, что могу получить последнюю запись за последний год для одного продукта следующим образом:

Report.objects.filter(date__year=2009, product_name="corn").order_by("-date")[0]

Я знаю, что могу группировать записи по названию следующим образом:

Report.objects.values("product_name")

Но как я могу получить количество для последней записи для каждого продукта? Я чувствую, что я сделал бы это в SQL (не уверен, мой SQL ржавый):

SELECT product_name, quantity FROM report WHERE YEAR(date) == 2009 GROUP_BY product_name HAVING date == Max(date)

Я предполагаю использовать объект Max () с аннотацией, но я не знаю, как это сделать.

На данный момент я делаю это вручную, добавляя последний элемент каждого запроса для каждого списка product_name, которое я не могу перечислить.

1 Ответ

2 голосов
/ 09 марта 2010

Не совсем тривиальный запрос, использующий либо Django ORM, либо SQL. Мой первый взгляд на это будет в значительной степени то, что вы, вероятно, уже делаете; получить отдельные пары продукта и даты, а затем выполнить отдельные запросы для каждого из них.

year_products = Product.objects.filter(year=2009)
product_date_pairs = year_products.values('product').distinct('product'
        ).annotate(Max('date'))
[Report.objects.get(product=p['product'], date=p['date__max']) 
        for p in product_date_pairs]

Но вы можете сделать шаг вперед с помощью оператора Q и некоторого необычного ИЛИ, чтобы сократить количество запросов до 2 вместо N + 1.

import operator
qs = [Q(product=p['product'], date=p['date__max']) for p in product_date_pairs]
ored_qs = reduce(operator.or_, qs)
Report.objects.filter(ored_qs)
...