Django:按不同列按最新过滤

rra*_*nza 6 python sql django aggregate distinct

有了这个FruitBasket模型,

水果篮(模型)类:
    水果= CharField(max_length = 128)
    计数= PositiveIntegerField()

还有这个样本数据

id水果数
----- ---------- -----
0苹果10
1个香蕉20
2苹果5
3香蕉30

我想要一个Django查询,它返回以下项目:

[(2,苹果,5),(3,香蕉,30)]

本质上,获取每个水果的“最新”行(在此示例中,我将时间戳简化为rowid。)

Fra*_*llo 7

https://docs.djangoproject.com/en/dev/ref/models/querysets/#distinct

q = FruitBasket.objects.distinct('fruit')
Run Code Online (Sandbox Code Playgroud)

仅在使用postgres时有效。

仅在PostgreSQL上,您可以传递位置参数(* fields)以指定DISTINCT应该应用的字段名称。这将转换为SELECT DISTINCT ON SQL查询。这是区别。对于正常的distinct()调用,数据库在确定哪些行不同时会比较每行中的每个字段。对于具有指定字段名称的distinct()调用,数据库将仅比较指定的字段名称。

另外,您必须指定一个order_by,并且不能在时间戳记之前指定:

q = FruitBasket.objects.distinct('fruit').order_by('fruit')
Run Code Online (Sandbox Code Playgroud)

当指定字段名称时,必须在QuerySet中提供order_by(),并且order_by()中的字段必须以相同的顺序从distinct()中的字段开始。

例如,SELECT DISTINCT ON(a)为列a中的每个值提供第一行。如果您不指定订单,则会得到一些任意行。

但是,values如果您可以取消要求,则可以使您更接近:通过具有相同顺序中的相同值来实现distinct / order_。

q = (
    FruitBasket.objects
    .values('id', 'fruit', 'count')
    .distinct('fruit').order_by('-id')
)
Run Code Online (Sandbox Code Playgroud)

实际上,有时最好脱离ORM

SELECT id, fruit, count 
FROM FruitBasket
GROUP BY fruit  
ORDER BY id DESC
Run Code Online (Sandbox Code Playgroud)

错误的查询

所以这个查询不是魔术...

SELECT * FROM (SELECT id, fruit, count 
FROM FruitBasket
ORDER BY id DESC) t
GROUP BY t.fruit
Run Code Online (Sandbox Code Playgroud)

更好,但仍然很恐怖

这些更好,但有点丑陋。

自行优化:

q = FruitBasket.objects.raw("""\
    SELECT * FROM 
    (
        SELECT id, fruit, count 
        FROM FruitBasket 
        ORDER BY id DESC
    ) t
    GROUP BY t.fruit
""")
Run Code Online (Sandbox Code Playgroud)

  • 我的意思是,如果它能够正常工作,那将是理想的选择,唯一可行的解​​决方案是最底层的解决方案。顶部解释了为什么orm无法执行您需要的操作。 (2认同)