查询集选择组的最新记录
Posted
技术标签:
【中文标题】查询集选择组的最新记录【英文标题】:Queryset select latest record for group 【发布时间】:2018-07-15 09:51:37 【问题描述】:使用 Django 1.65 Python 3.4.1 甲骨文数据库
数据库“位置”中的表:
location | update_time | num_01 | num_02 | num_03 |
-----------+-----------------+-----------+--------+--------
B | 06 Feb 18 04:14 | 42 | 43 | 55
C | 22 Feb 17 04:14 | 77 | 99 | 23
A | 05 Feb 18 04:14 | 48 | 43 | 21
A | 01 Feb 18 04:14 | 82 | 83 | 74
我想为每个位置选择具有最新 update_time 的行。
上表的结果应该是:
location | update_time | num_01 | num_02 | num_03 |
-----------+-----------------+-----------+--------+--------
A | 05 Feb 18 04:14 | 48 | 43 | 21
B | 06 Feb 18 04:14 | 42 | 43 | 55
C | 22 Feb 17 04:14 | 77 | 99 | 23
我可以使用查询集返回每个位置的最新更新时间:
latest_updates = Locations.objects.values('location').annotate(max_date=Max('update_time')).order_by('location')
但这只会在我查找整行时返回位置和最大更新时间 - num_01、num_02、num_03。
我花了很多时间搜索 ***,但没有什么适合的。 Oracle 似乎不支持我可以开始工作的排序方式和不同的选项。
由于某种原因,我无法导入子查询,所以这对我来说不是一个选择,我坚持使用这个版本的 django 等,因为它正在工作。
该表最终将包含合理数量的数据,因此如果可能,我正在寻找一个合理有效的解决方案。
【问题讨论】:
【参考方案1】:你可以试试这个:
Locations.objects.order_by('location', '-update_time').distinct('location')
就我而言,它适用于 Django 2.1
【讨论】:
这对于 sqlite 来说效果不佳(我原以为测试的默认数据库引擎)会产生NotImplementedError: DISTINCT ON fields is not supported by this database backend
。使用无法跨不同支持的引擎移植的数据库抽象有点毫无意义。【参考方案2】:
对于 Django 1.11+,你也可以Subquery,所以这样的东西应该可以工作:
from django.db.models import Subquery, OuterRef, F
qs = Location.objects.all()
# make a subquery (filter, order, get 'id')
sq = qs.filter(location=OuterRef('location')).order_by('-update_time').values('id')
# use subquery in your query (via annotation + filter)
qs.annotate(latest=Subquery(sq[:1])).filter(id=F('latest'))
【讨论】:
【参考方案3】:你应该使用,
latest_updates = Locations.objects.order_by('location', '-update_time').distinct('location')
【讨论】:
那只会返回整个表的最大更新时间?我想要每个营业地点组的最大 update_time。 "我想为每个位置选择具有最新 update_time 的行。" 我明白了。请检查我更新的答案。看看它是否适用于您的所有情况。 谢谢,那是关于 Oracle 不支持不同字段的部分。错误是:“此数据库后端不支持 DISTINCT ON 字段”。 :-/【参考方案4】:我在这里找到的最佳解决方案:https://gist.github.com/ryanpitts/1304725
'''
given a Model with:
category = models.CharField(max_length=32, choices=CATEGORY_CHOICES)
pubdate = models.DateTimeField(default=datetime.now)
<other fields>
Fetch the item from each category with the latest pubdate.
'''
model_max_set = Model.objects.values('category').annotate(max_pubdate=Max('pubdate')).order_by()
q_statement = Q()
for pair in model_max_set:
q_statement |= (Q(category__exact=pair['category']) & Q(pubdate=pair['max_pubdate']))
model_set = Model.objects.filter(q_statement)
【讨论】:
以上是关于查询集选择组的最新记录的主要内容,如果未能解决你的问题,请参考以下文章
复杂Rails Active Record查询选择具有真实结果的记录,以便当天最新更新其他创建的记录