Postgresql上带order_by、distinct和limit的Django查询
我有以下资料:Postgresql上带order_by、distinct和limit的Django查询,django,postgresql,django-queryset,Django,Postgresql,Django Queryset,我有以下资料: class Product(models.Model): name = models.CharField(max_length=255) class Action(models.Model): product = models.ForeignKey(Product) created_at = models.DateTimeField(auto_now_add=True) 我想检索由created_at DESC订购的10项最新操作,这些操作具有不同的产
class Product(models.Model):
name = models.CharField(max_length=255)
class Action(models.Model):
product = models.ForeignKey(Product)
created_at = models.DateTimeField(auto_now_add=True)
我想检索由created_at DESC订购的10项最新操作,这些操作具有不同的产品
以下内容与结果接近,但仍未排序:
Action.objects.all().order_by('product_id').distinct('product_id')[:10]
编辑:此解决方案有效,但Ross Lote的更干净 这就是我最终的做法,使用: 通过设置
值(“产品id”)
我们对产品id进行分组
使用annotate()
我们只能在values()
或annotate()
中使用的字段上使用order\u by。由于对于每个操作,created_at字段自动设置为now,因此在created_at上排序与在id上排序相同,使用注释(action_id=Max('id'))。按('-action_id')
排序是正确的方法
最后,我们只需要对查询进行切片[:10]
希望这能有所帮助。您的解决方案似乎做得太多了。它还将导致两个单独的SQL查询。这将很好地工作,并且只需要一个查询:
action_ids = Action.objects.order_by('product_id', '-created_at')\
.distinct('product_id').values_list('id', flat=True)
result = Action.objects.filter(id__in=action_ids)\
.order_by('-created_at')[:10]
您是否尝试过颠倒
order\u by()
和distinct()
调用的顺序?Django的文档说明:“指定字段名时,必须在QuerySet中提供order\u by(),order\u by()中的字段必须以distinct()中的字段开头,顺序相同。”。您的订单是通过product\u id
,而不是在创建的。为什么?因为为了使distinct('product_id')起作用,您必须在order_by子句中指定它。但是,您可以有多个参数来order_by。根据他们刚才提供的链接示例,您似乎可以这样做:.order\u by('product\u id','created\u at')。distinct('product\u id')
使用'values\u list'是一个好主意,因为它可以保存一个查询。我相应地编辑了我的答案。你试过运行我的代码吗?第一行将正常运行,因为第一个order\u by
和distinct
是相同的。在
创建的第一个
-确保您只能获得每个产品的最新操作(此时,它们的顺序可能不正确)。第二行只是将操作按正确的顺序排列,但仍然保持在相同的查询中。感谢您的解释,您是对的!你的代码运行得很好,比我的好!谢谢:)我仍然不明白为什么我们不能只在一行中这样做,比如Action.objects.order\u by('product\u id','-created\u at')。distinct('product\u id')[:10]
。我之所以这么说是因为我试图使用.distinct(…).filter(…)
,而且似乎过滤器是在distinct之前“执行”的。。。
action_ids = Action.objects.order_by('product_id', '-created_at')\
.distinct('product_id').values_list('id', flat=True)
result = Action.objects.filter(id__in=action_ids)\
.order_by('-created_at')[:10]