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

在Django中筛选Code唯一值并保留最新添加记录的解决方案

按Code去重并保留最新记录的解决方案

需求说明

现有数据表包含id、code、name、status、user_id字段,需按code字段去重,且保留每个code对应的最新添加记录。

原始数据

id    Code         name     status   last added

1     23-07-00001  red       1          2023-07-11 02:48:41.025713
2     23-07-00002  orange    2          2023-07-11 02:48:41.025713
3     23-07-00003  blue      3          2023-07-12 05:18:47.534430
4     23-07-00002  orange    4          2023-07-12 05:24:40.485039

期望结果

1     23-07-00001  red       1          2023-07-11 02:48:41.025713
3     23-07-00003  blue      3          2023-07-12 05:18:47.534430
4     23-07-00002  orange    4          2023-07-12 05:24:40.485039

尝试过的无效代码

item_data = TevIncoming.objects.filter(status__in=retrieve).select_related().values_list('code', flat=True).distinct().order_by('-incoming_in').reverse()

注:这段代码仅返回去重后的code值,且distinct与order_by结合时会受排序字段影响,无法直接获取完整的最新记录。


解决方案

Django原生方案

方法1:子查询获取最新记录ID(推荐)

通过子查询定位每个code对应的最新记录ID,再筛选出这些记录,准确性最高:

from django.db.models import Subquery, OuterRef

# 子查询:获取每个code的最新记录ID(按incoming_in倒序取第一条)
latest_record_ids = TevIncoming.objects.filter(
    status__in=retrieve,
    code=OuterRef('code')
).order_by('-incoming_in').values('id')[:1]

# 筛选出所有最新记录
item_data = TevIncoming.objects.filter(
    status__in=retrieve,
    id__in=Subquery(latest_record_ids)
).select_related()

方法2:先获取最新时间再关联查询

先统计每个code的最新添加时间,再匹配对应的记录:

from django.db.models import Max

# 统计每个code的最新incoming_in时间
latest_times = TevIncoming.objects.filter(status__in=retrieve) \
    .values('code') \
    .annotate(latest_in=Max('incoming_in'))

# 匹配时间和code,获取完整记录
item_data = TevIncoming.objects.filter(
    status__in=retrieve,
    code__in=latest_times.values('code'),
    incoming_in__in=latest_times.values('latest_in')
).select_related()

注:若存在同一code多条记录添加时间完全相同的情况,此方法会返回多条,需根据业务补充筛选逻辑(如取最大id)。

SQL原生方案

方法1:窗口函数(推荐,支持PostgreSQL、MySQL 8.0+、SQL Server等)

用ROW_NUMBER()窗口函数按code分组并排序,取每组第一条:

SELECT id, code, name, status, last_added
FROM (
    SELECT 
        id, code, name, status, last_added,
        -- 按code分组,按添加时间倒序编号
        ROW_NUMBER() OVER (PARTITION BY code ORDER BY last_added DESC) AS row_num
    FROM tev_incoming
    WHERE status IN (1,2,3,4) -- 替换为你的retrieve列表值
) AS sub_query
WHERE row_num = 1;

方法2:关联查询(兼容老版本数据库)

先分组获取每个code的最新时间,再关联原表获取记录:

SELECT t1.*
FROM tev_incoming t1
INNER JOIN (
    SELECT code, MAX(last_added) AS latest_time
    FROM tev_incoming
    WHERE status IN (1,2,3,4) -- 替换为你的status值
    GROUP BY code
) t2 
ON t1.code = t2.code AND t1.last_added = t2.latest_time
WHERE t1.status IN (1,2,3,4);

注:若同一code存在相同最新时间的记录,此方法会返回多条,可添加AND t1.id = (SELECT MAX(id) FROM tev_incoming WHERE code = t2.code AND last_added = t2.latest_time)来取最大ID的记录。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 09:23:17