带有 order_by 的 Django 查询,在 Postgresql 上有区别和限制
Django query with order_by, distinct and limit on Postgresql
我有以下内容:
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 的更干净
这是我最终做到的方式,使用 Django Aggregation:
from django.db.models import Max
actions_id = Action.objects.all().values('product_id') \
.annotate(action_id=Max('id')) \
.order_by('-action_id')[:10] \
.values_list('action_id', flat=True)
result = Action.objects.filter(id__in=actions_id).order_by('-created_at')
通过设置 values('product_id')
,我们在 product_id.
上按 进行 分组
使用 annotate()
我们只能在 values()
或 annotate()
中使用的字段上使用 order_by。由于对于每个操作,created_at 字段自动设置为现在,在 created_at 上的排序与在id,使用annotate(action_id=Max('id')).order_by('-action_id')
是正确的方法。
最后,我们只需要对查询进行切片 [:10]
希望对您有所帮助。
您的解决方案似乎试图做太多事情。它还将导致 2 个单独的 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]
我有以下内容:
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 的更干净
这是我最终做到的方式,使用 Django Aggregation:
from django.db.models import Max
actions_id = Action.objects.all().values('product_id') \
.annotate(action_id=Max('id')) \
.order_by('-action_id')[:10] \
.values_list('action_id', flat=True)
result = Action.objects.filter(id__in=actions_id).order_by('-created_at')
通过设置 values('product_id')
,我们在 product_id.
使用 annotate()
我们只能在 values()
或 annotate()
中使用的字段上使用 order_by。由于对于每个操作,created_at 字段自动设置为现在,在 created_at 上的排序与在id,使用annotate(action_id=Max('id')).order_by('-action_id')
是正确的方法。
最后,我们只需要对查询进行切片 [:10]
希望对您有所帮助。
您的解决方案似乎试图做太多事情。它还将导致 2 个单独的 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]