我们希望以这样一种方式获取父子,它给了我最近的10个父母,每个父母只有一个最新的儿童记录。
例如:
Category
- id
- name
- created_date
Item
- id
- name
- category
- created_date
使用上面指定的模型结构,我想获取最新的10个类别以及每个类别的最新子项。
只有一个查询到服务器我想访问所有数据。
Category1.name, Category1.id, LatestItemForCat1.name, LatestItem1ForCat1.created_date
Category2.name, Category2.id, LatestItemForCat2.name, LatestItem1ForCat2.created_date
Category3.name, Category3.id, LatestItemForCat3.name, LatestItem1ForCat3.created_date
使用django ORM实现此目的的最佳方法是什么。
这可以通过以下sql查询获得。我更愿意使用django ORM来解决这个问题。或者更好的SQL查询。
select c.name, c.id, i.name, i.created_date
from
category c
inner join
item i
on c.id = i.category_id
where i.id = (select id from item order by created_date desc limit 0,1)
limit 10
答案 0 :(得分:3)
您可以使用原始SQL,并且您的查询看起来很好(在最终限制之前只缺少“c.created_date desc的顺序”。
原始SQL解决方案中的子查询并没有比返回类别模型中的最后10个条目的方法好得多,类似于此(未经测试的)样本:
class Category(models.Model):
...
def last10items(self):
return self.item_set.order_by('-created_date')[:10]
我们最多谈论100条记录,我不担心效率,因为后续查询就像是要点击缓存(有几层缓存:django,数据库和操作系统)。这样,您可以传递最后10个类别并从模板中调用last10items:
{% for category in categories %}
...
{% for item in category.last10items %}
...
我确信有些混蛋会因为这样说而拒绝我:除非你需要,否则不要试图优化某些东西。在许多情况下,我感到惊讶的是,在对代码进行分析之前,我对一种方法的效率有多么错误。阅读“Python Patterns - An Optimization Anecdote”。
答案 1 :(得分:0)
如果您获得每个类别的项目,则必须为每个类别访问一次数据库,因此最好以相反的方式执行此操作并使用select_related
来获取类别属于没有额外命中的项目:
items = Item.objects.order_by('-category__created_date', '-created_date').select_related()
i = 0
cat = None
for item in items:
if item.category != cat:
print "%s: %s" % (item.category, item)
cat = item.category
i += 1
if i == 10:
break
我添加了一个带有计数器的for循环,只显示10个类别和一个项目,我不认为如果这样做就可以通过ORM限制它!