【问题标题】:Django: select values with max timestamps or join to the same tableDjango:选择具有最大时间戳的值或加入同一个表
【发布时间】:2026-02-02 00:05:01
【问题描述】:

我有一个简单的 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 方法添加到 Server 模型中,该方法将返回当前服务器的所有最后属性。我的意思是它应该返回当前服务器的所有属性名称的名称和值,并且每个 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 解决方案。你能帮帮我吗?

【问题讨论】:

    标签: python sql django postgresql


    【解决方案1】:

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

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

    来自PostgreSQL documentation

    SELECT DISTINCT ON (表达式 [, ...] ) 只保留第一行 给定表达式计算结果为等于的每组行。这 DISTINCT ON 表达式使用与 for 相同的规则进行解释 订购(见上文)。请注意,每组的“第一行”是 不可预测,除非使用 ORDER BY 来确保所需的行 首先出现。

    您可以在sql fiddle demo查看和尝试。

    可以将这个语法从django documentation翻译成django:

    仅在 PostgreSQL 上,您可以在 为了指定 DISTINCT 应​​该到的字段的名称 申请。这将转换为 SELECT DISTINCT ON SQL 查询。

    所以在 django 中会是这样的:

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

    【讨论】:

      最近更新 更多