Django:选择具有最大时间戳记的值或加入同一张表


问题内容

我有一个简单的Django模型

class Server(models.Model):
    name = models.CharField(max_length=120)

class ServerPropertie(models.Model):
    name = models.CharField(max_length=120)
    value = models.CharField(max_length=120)
    timestamp = models.DateTimeField()
    server = models.ForeignKey(Server)

我想将get_properties方法添加到服务器模型,该方法将返回当前服务器的所有最后一个属性。我的意思是,它应返回当前服务器的所有属性名称的名称和值,并且每个uniq属性名称应具有一个值,该行具有最大时间戳。

我可以在原始硬编码的原始SQL中执行此操作(我使用postgres):

SELECT t1.name, t1.value FROM environments_serverpropertie t1
JOIN (SELECT max("timestamp") "timestamp", name 
      FROM environments_serverpropertie
      group by name) t2 on t1.name = t2.name and t1.timestamp = t2.timestamp;

或在python中,但我相信存在pythonic解决方案。请你帮助我好吗。


问题答案:

如果您使用的是PostgreSQL,通常的语法是:

select distinct on (name)
    name, value
from environments_serverpropertie
where server = ...
order by name, timestamp desc

PostgreSQL文档中

SELECT DISTINCT ON(expression [,…])仅保留给定表达式等于的每组行的第一行。使用与ORDER
BY相同的规则来解释DISTINCT ON表达式(请参见上文)。请注意,除非使用ORDER
BY来确保所需的行首先出现,否则每个集合的“第一行”都是不可预测的。

您可以在中查看并尝试 sql fiddle demo

可以从django文档中将此语法转换为django

仅在PostgreSQL上,您可以传递位置参数(* fields)来指定DISTINCT应该应用的字段名称。这将转换为SELECT DISTINCT
ON SQL查询。

因此在django中,它将类似于:

ServerPropertie.objects.filter(...).order_by('name', '-timestamp').distinct('name')