首页 > 解决方案 > 选择具有最大字段/列值的实例/行,每个字段/列(分组依据)

问题描述

所以,我有这些模型:

class Computer(models.Model):
    hostname = models.CharField(primary_key=True, max_length=6)
    <other computer info fields>

class ComputerRecord(models.Model):
    id = models.AutoField(primary_key=True)
    pc = models.ForeignKey(Computer, on_delete=models.CASCADE)
    ts = models.DateTimeField(blank=False)
    <other computerrecord info fields>

我想获取ts每个pc(计算机模型)具有最大值的行/计算机记录实例

在 sql 中会是这样的:

SELECT hub_computerrecord.*
FROM hub_computerrecord
JOIN (
    SELECT pc_id, MAX(ts) AS max_ts
    FROM hub_computerrecord
    GROUP BY pc_id
) AS maxs ON hub_computerrecord.pc_id = maxs.pc_id
WHERE hub_computerrecord.ts = maxs.max_ts;

注意(编辑):有很多ComputerRecord实例(10000+)所以任何效率太低的东西都行不通

标签: djangodjango-orm

解决方案


尝试这个

from django.db.models import Max, F

qs = ComputerRecord.objects.annotate(
    max=Max('pc__computerrecord__ts')
).filter(
    ts=F('max')
)

是的,这个表单表达式不会在 OP 中构建精确的SQL 查询,但它会产生相同的结果(可能存在一些性能问题,不确定矩阵)

raw()或者,您可以使用以下方法执行原始 SQL

raw_query = """
SELECT hub_computerrecord.*
FROM hub_computerrecord
JOIN (
    SELECT pc_id, MAX(ts) AS max_ts
    FROM hub_computerrecord
    GROUP BY pc_id
) AS maxs ON hub_computerrecord.pc_id = maxs.pc_id
WHERE hub_computerrecord.ts = maxs.max_ts;
"""

qs = ComputerRecord.objects.raw(raw_query)

推荐阅读