【问题标题】:django get latest for each group, group by foreign keydjango 获取每个组的最新信息,按外键分组
【发布时间】:2015-02-05 22:15:33
【问题描述】:

假设我有类似这些模型的东西:

class Product(models.Model):
  name = models.CharField(max_length=50)

class Sale(models.Model):
  product = models.ForeignKey(Product)
  sale_date = models.DateField()

我想了解每种产品的最新销售情况。最新表示最新的销售日期。此外,在同一个查询中,我想获取每种产品的销售数量。

在 SQL 术语中,我需要按 product_id 分组,以计算每个产品的销售数量(即每个组的长度)。并且也许还可以按日期订购(在每个组中也是如此)以获得最新的产品销售。

使用 django ORM,我意识到我需要以某种方式使用 annotate() 并且可能与 values() 结合使用。但我还没想好怎么做。

假设我有这个 products 表:

| id |   name    |    
===================
| 1  | Book      |  
| 2  | Telephone |

还有这个sales表:

| id | product_id | sale_date |
=================================
| 1  |      1     | 05-02-2015 |
| 2  |      2     | 04-02-2015 |
| 3  |      2     | 03-02-2015 |
| 4  |      1     | 06-02-2015 |
| 5  |      1     | 01-02-2015 |

我想得到如下输出:

| product_id |    name   | sale_date  | num_sales |
====================================================
|     1      | Book      | 06-02-2015 |     3     |
|     2      | Telephone | 04-02-2015 |     2     |

因为 06-02-2015 是 product_id=1(图书)的最晚销售日期,而 04-02-2015 是 product_id=2(电话)的最晚销售日期。

【问题讨论】:

    标签: django count group-by


    【解决方案1】:
    from django.db.models import Count, Max
    query = Product.objects.annotate(num_sales=Count('sale'))
    query = query.annotate(latest_sale_date=Max('sale__sale_date'))
    for prod in query.all():
        print (prod.pk, prod.name, prod.latest_sale_date, prod.num_sales)
    

    你会得到如下输出:

    (1, u'Book', datetime.date(2015, 6, 2), 3)
    (2, u'Telephone', datetime.date(2015, 4, 2), 2)
    

    类似于您在问题中的预期输出。请注意,您传递给 annotate 的任何 kwarg 都会成为查询结果的属性。

    【讨论】:

    • 谢谢。它确实有效。但我想了解一些事情。我知道 annotate() 为产品对象创建了一个新属性。但是如何使用像 Count() 这样的函数呢?您使用的参数不是产品模型(“销售”)中的列,所以我很困惑。其次,查询结束时调用 all() 重要吗?
    • 我使用您在 Django 1.7 中的新测试应用程序中发布的问题中发布的模型对此进行了测试。我可能是错的,但我相信“销售”只是 Django 的一部分自动为您填充 FK 关系,它只是将类名小写来生成它。我不认为all 是绝对必要的,因为 QuerySet 对象是可迭代的,但我最近写了太多 SQLAlchemy。我不认为有它在那里有什么坏处。
    • 当我测试通过查看 connection.queries 变量生成的查询时,我看到一个查询包含两列的 group by 子句。我认为这是一个低效的查询?
    猜你喜欢
    • 2013-11-24
    • 1970-01-01
    • 1970-01-01
    • 2017-09-27
    • 1970-01-01
    • 1970-01-01
    • 2020-05-04
    • 1970-01-01
    相关资源
    最近更新 更多