【问题标题】:How do I get the values of the lastest entries grouped by an attributes using Django ORM?如何使用 Django ORM 获取按属性分组的最新条目的值?
【发布时间】:2011-01-25 12:33:50
【问题描述】:

我有一个看起来有点像这样的报表模型:

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() 对象,但我不知道该怎么做。

目前,我通过手动添加每个查询的最后一项来为每个我无法单独列出的产品名称添加。

【问题讨论】:

    标签: django model filter aggregate


    【解决方案1】:

    不完全是使用 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 运算符和一些花哨的 OR'ing 将您的查询计数减少到 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)
    

    【讨论】:

    • +1 当然,如果有很多产品,它可能是一个loooooooooooooooog第二个查询。也许我会坚持第一个解决方案,除非我遇到一些性能问题。考虑到数据库将是 sqlite,知道第二个是否真的更快会很有趣。
    • 非常正确,事情可能会变得疯狂。尝试两者并比较性能。如果您在 shell 中评估性能,请查看 django.db.connection.queries。
    猜你喜欢
    • 1970-01-01
    • 2019-10-11
    • 2020-10-27
    • 1970-01-01
    • 2017-02-28
    • 1970-01-01
    • 2013-07-27
    • 2018-08-12
    • 1970-01-01
    相关资源
    最近更新 更多