You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django中获取每个tagid对应的最新一条数据?

问题描述

我有如下Django抽象模型:

class TagDataBase(BaseModel):
    tagid = models.IntegerField(primary_key=True)
    intvalue = models.BigIntegerField(blank=True, null=True)
    floatvalue = models.FloatField(blank=True, null=True)
    stringvalue = models.CharField(max_length=255, blank=True, null=True)
    datevalue = models.DateTimeField(blank=True, null=True)
    dataintegrity = models.IntegerField(blank=True, null=True)
    t_stamp = TimestampField()

    class Meta:
        managed = False
        abstract = True
        db_table = 'sqlt_data_1_2023_02'
        unique_together = (('tagid', 't_stamp'),)

该模型为抽象类,数据库表会动态变化,我通过get_model()获取模型类。当前执行的查询如下:

tag_ids = [list of tagid]
q = Q(tagid__in=tag_ids, dataintegrity=192)
items = get_model().objects.filter(q).order_by('-t_stamp')

这个查询能正常运行,但会返回数十万条冗余数据。我仅需要每个tagid对应的最新数据(按t_stamp降序排列的第一条)。

注意事项:

  • 模型不由Django管理,无法修改字段
  • 使用的数据库为MariaDB 10.9
解决方案

针对MariaDB 10.9的特性,推荐两种高效实现方式:

方法1:使用窗口函数RowNumber()

利用Django的Window和RowNumber函数,按tagid分组并按t_stamp降序标记行号,再筛选每组的第一条数据:

from django.db.models import Window, F
from django.db.models.functions import RowNumber

tag_ids = [list of tagid]
model_cls = get_model()

# 为每条数据标注其在对应tagid组内的行号(按t_stamp降序)
annotated_items = model_cls.objects.filter(
    tagid__in=tag_ids,
    dataintegrity=192
).annotate(
    row_num=Window(
        expression=RowNumber(),
        partition_by=F('tagid'),
        order_by=F('t_stamp').desc()
    )
)

# 筛选出每组的第一条记录
latest_items = annotated_items.filter(row_num=1)

该方法生成的SQL利用窗口函数一次性完成分组排序与筛选,性能最优,避免冗余数据加载到内存。

方法2:子查询获取每个tagid的最新t_stamp

先查询每个tagid对应的最新t_stamp,再关联获取对应数据:

from django.db.models import Subquery, OuterRef

tag_ids = [list of tagid]
model_cls = get_model()

# 子查询:获取单个tagid的最新t_stamp
latest_tstamp_subquery = model_cls.objects.filter(
    tagid=OuterRef('tagid'),
    dataintegrity=192
).order_by('-t_stamp').values('t_stamp')[:1]

# 主查询:匹配tagid和对应最新t_stamp
latest_items = model_cls.objects.filter(
    tagid__in=tag_ids,
    dataintegrity=192,
    t_stamp=Subquery(latest_tstamp_subquery)
)

这种方法兼容性强,适合不熟悉窗口函数的场景,数据量极大时性能略逊于方法1。

关键注意点

  • 依赖模型中已定义的unique_together = (('tagid', 't_stamp'),)约束,避免单个tagid出现多条相同t_stamp的最新数据
  • 两种方法均只会返回每个tagid的唯一最新记录,不会加载冗余数据

内容的提问来源于stack exchange,提问作者cclloyd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 14:35:10