Django,按一个字段分组,仅取每个分组的最新/最大值,然后取回ORM对象

时间:2020-01-24 09:38:00

标签: python django django-models orm

我有以下Django(3.0)ORM模型:

class Portfolio(models.Model):
    code = models.CharField(max_length=20)
    name = models.CharField(max_length=100)
    date = models.DateField()
    created = models.DateTimeField(blank=True, null=True, auto_now_add=True)

我想按code字段对它们进行分组,并且对于每个代码,仅采用最大date的投资组合

我知道我可以使用以下查询:

Portfolio.objects.values('code').annotate(latest=Max('date'))

但是它有三个问题:

  1. 它仅给我codelatest字段,因此我丢失了其他字段
  2. 它返回字典,而我需要一个实际的Portfolio对象列表
  3. Max之所以有效是因为dateDateField。它也可以在其他数字字段类型上使用,但是如果我想按CharField的值(字典顺序)对记录进行排序(例如name并为每个组获取第一条记录怎么办?

因此,总而言之,我的问题是:如何使用Django ORM检索按一个或多个字段分组的ORM对象的列表,并仅返回每个组的第一条记录,并赋予任意“顺序” ”子句?

1 个答案:

答案 0 :(得分:2)

从组中获取第一个/最后一个值 正是使用ORDER BY进行DISTINCT ON SQL子句can be used for但afaik 仅在Postgresql中。在MySQL中,仅DISTINCT,没有ON,所以-not possible(直接),SQLite也不支持{ 1}},只是DISTINCT ON。为此,在Django positional arguments to .distinct()中只能在Postgresql中传递)。

在Django中,我们可以使用 QuerySet 这样操作:

DISTINCT

在此,我们使用空的Portfolio.objects.order_by().order_by( 'code', # first, cause we want to group by this value '-created' # descending order, latest / max will be first ).distinct('code') 调用 __清除 QuerySet 上所有已存在的排序__ (已添加或默认),以确保仅对必需的排序应用.order_by()分组才能正常工作。


一般使用方式:

  • 使用过滤器开始 QuerySet -.order_by(...)

  • 已在 QuerySet -q = SomeModel.objects.filter(col1__gt=2)

    上设置的
  • 清晰排序

  • 添加排序顺序,首先是分组列(以后用于q.order_by()),后面是附加列-distinct

    这里:

    • 'col1','col2','col3'-是我们要q.order_by('col1', '-col2', '-col3', '-date1')(用于分组)的列/字段

    • 'col1','-col2','-col3'-我们要分组的列相同,但是要用于分组的顺序(对于所有子列都是至关重要的-groups-组中的所有列均列出第一个-对于它们,这将影响从组-'first''last'获取的结果行;对于第一列,它不会影响结果行,只会影响结果排序)

    • '-date1'-我们选择用来对最终组行进行排序的任何其他排序列
  • 最后将GROUP BY子句添加我们选择要分组的字段作为参数,其顺序与.distinct()子句中的顺序-.order_by()