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

使用distinct与order_by关联模型字段时重复记录问题求解

问题翻译

我调用按product__company__name排序的API时,返回结果排序符合预期但存在两条重复记录。查阅Django 3.2文档中distinct方法的说明:

如果你根据关联模型的字段排序,这些字段会被添加到查询的选中列中,这可能会让原本重复的行变得看起来不重复。由于这些额外的列不会出现在返回结果里(它们仅用于支持排序),所以有时候看起来像是返回了非重复结果,但实际并非如此。

我仅需按公司名称对产品进行排序,请问该如何解决此问题?

原代码片段:

def get_queryset(self):
        qs = MyModel.objects.filter(
               <logic_code>
        )
        return qs.distinct().order_by("product__company__name")

解决方案

方法1:通过子查询先排序再去重

由于order_by引入的关联表字段会干扰distinct的判断,我们可以先通过子查询完成排序,再基于主键列表获取去重后的结果,同时保留排序顺序:

def get_queryset(self):
    # 子查询:完成排序并获取主键列表
    sorted_pks = MyModel.objects.filter(
        <logic_code>
    ).order_by("product__company__name").values_list("pk", flat=True)
    # 基于主键列表查询,自动去重并保持排序
    qs = MyModel.objects.filter(pk__in=sorted_pks).distinct()
    return qs

方法2:用annotate引入排序字段后去重

将关联的公司名称通过annotate添加为当前模型的查询字段,让distinct能基于主模型字段+排序字段正确判断重复:

from django.db.models import F

def get_queryset(self):
    qs = MyModel.objects.filter(
        <logic_code>
    ).annotate(company_name=F("product__company__name")) \
      .order_by("company_name") \
      .distinct("id", "company_name")
    return qs

注:Django 3.2支持distinct指定字段,这里指定id(主模型唯一标识)和company_name,避免关联表字段的干扰,确保去重准确。

方法3:针对按公司名称去重的场景(按需使用)

如果你的需求是每个公司名称仅保留一条记录,可以直接在distinct中指定关联字段:

def get_queryset(self):
    qs = MyModel.objects.filter(
        <logic_code>
    ).order_by("product__company__name").distinct("product__company__name")
    return qs

此方法会保留每个公司名称对应的第一条记录,适合仅需按公司分组展示的场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 12:20:54