我有一个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
。
答案 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]