鉴于此FruitBasket模型,
class FruitBasket(Model): fruit = CharField(max_length=128) count = PositiveIntegerField()
这个样本数据,
id fruit count ----- ---------- ----- 0 apple 10 1 banana 20 2 apple 5 3 banana 30
我想要一个返回以下项目的django查询:
[(2,apple,5),(3,banana,30)]
基本上,抓住最新的" row per fruit(我在此示例中简化了rowid的时间戳。)
答案 0 :(得分:6)
https://docs.djangoproject.com/en/dev/ref/models/querysets/#distinct
q = FruitBasket.objects.distinct('fruit')
仅在使用postgres时才有效。
仅在PostgreSQL上,您可以传递位置参数(*字段) 命令指定DISTINCT应该应该的字段的名称 应用。这转换为SELECT DISTINCT ON SQL查询。这是 区别。对于正常的distinct()调用,数据库会比较每个 确定哪些行是不同的时,每行中的字段。为一个 distinct()调用指定的字段名称,数据库只会 比较指定的字段名称。
此外,您必须指定order_by,它不能通过时间戳:
q = FruitBasket.objects.distinct('fruit').order_by('fruit')
指定字段名称时,必须在中提供order_by() QuerySet和order_by()中的字段必须以字段开头 distinct(),顺序相同。
例如,SELECT DISTINCT ON(a)为每个提供第一行 列a中的值。如果您没有指定订单,您将获得一些订单 任意行。
然而,values
可能会让你更接近,如果你可以杀死这个要求:distinct / order_by具有相同顺序的相同值。
q = FruitBasket.objects.values('id', 'fruit', 'count').distinct('fruit').order_by('-id')
实际上,有时打破ORM更好。
SELECT id, fruit, count
FROM FruitBasket
GROUP BY fruit
ORDER BY id DESC
所以这个查询不是魔术......
SELECT * FROM (SELECT id, fruit, count
FROM FruitBasket
ORDER BY id DESC) t
GROUP BY t.fruit
这些更好但有点难看。
自行优化:
q = FruitBasket.objects.raw("SELECT * FROM (SELECT id, fruit, count FROM FruitBasket ORDER BY id DESC) t GROUP BY t.fruit")
答案 1 :(得分:1)
您可以尝试以下方法:
FruitBasket.objects.order_by('fruit', '-count').distinct('fruit')
就我而言,它适用于Django 2.1
答案 2 :(得分:1)
作为替代方案,如果您拥有固定(少量)的可能不同值,则可以使用多个查询(虽然不是最佳选择,但应该适用于小型项目):
available_fruits = ['banana', 'apple'] # can be also an extra query to extract distinct values
fruits = [FruitBasket.objects.filter(fruit=x).latest('id') for x in available_fruits ]
在我的情况下,它只有4个值,所以我可以进行4个简单而快速的查询。
答案 3 :(得分:1)
子查询可能会在这里帮助您, docs中的示例:
>>> from django.db.models import OuterRef, Subquery
>>> newest = Comment.objects.filter(post=OuterRef('pk')).order_by('-created_at')
>>> Post.objects.annotate(newest_commenter_email=Subquery(newest.values('email')[:1]))