Django ORM:使列上的对象不同并由另一列排序

时间:2014-05-27 18:14:51

标签: python django django-orm

我有一个Django模型(非常简化)看起来像这样:

class MyModel(models.Model):
    date = models.DateTimeField()
    number = models.PositiveIntegerField()

我希望按照它们出现的反向时间顺序获取唯一number的列表。

因此,例如使用此数据(date s在此处排序以获得更好的易读性):

date         | number
-------------+-------
24/12/2014   | 12
23/12/2014   | 8
22/12/2014   | 8
21/12/2014   | 5
20/12/2014   | 12
19/12/2014   | 5
18/12/2014   | 14

我会得到一个如下所示的列表:

[12, 8, 5, 14]

直观地说,我会像这样编写查询:

MyModel.objects.order_by('-date').distinct('number')

但这是无效的ORM代码。

我该如何解决这个问题?

请注意,有问题的表包含数百万行,可能会有很多重复的number s,因此我无法以“天真”的方式解决此问题(例如,从{{1如果之前没有看到过MyModel.objects.order_by('-date'),那么就快速拿起number

2 个答案:

答案 0 :(得分:2)

@mipadi's answer效果很好,但我更喜欢在代码库中避免使用原始SQL。

然而他的回答让我们更容易找到原生的ORM版本,所以多亏了他! 这是我提出的ORM版本:

 results = MyModel.objects.values('number').annotate(m=Max('date')).order_by('-m')
 results = [r.number for r in results]

似乎应该可以做到:

results = MyModel.objects.values('number').annotate(m=Max('date')).order_by('-m').values_list('number', flat=True)

但是使用Django 1.6时,在添加最后一个FieldError: Cannot resolve keyword 'm' into field.方法时出现values_list错误。可能有办法解决这个问题,但我并没有被2行版本所困扰,足以花时间搞清楚它。

答案 1 :(得分:1)

您可以使用SQL GROUP BY语句执行此操作,但事实是,我永远不会记得如何在Django的ORM中执行GROUP BY,因此我使用原始SQL:< / p>

number_qs = MyModel.objects.raw("""
    SELECT
        id, MAX(date) AS date, number
    FROM
        myapp_mymodel
    GROUP BY
        number
    ORDER BY
        MAX(date) DESC;
""")
numbers = [n.number for n in number_qs]