如何使用Django ORM删除bad_reviews表中指定字段的重复记录?
用Django ORM重写多字段重复记录查询
你需要基于client_id、survey_id、text、rating、privacy_agreement字段找出BadReviews模型中的重复记录,对应你提供的SQL查询,用Django ORM可以这样实现:
1. 还原原SQL的查询逻辑(找出所有重复记录)
先构建子查询筛选出存在重复的字段组合,再关联原表获取所有重复记录:
from django.db.models import Count, Exists, OuterRef # 第一步:找出存在重复的字段组合(对应SQL中的dupes子查询) duplicate_groups = BadReviews.objects.values( 'client_id', 'survey_id', 'text', 'rating', 'privacy_agreement' ).annotate(record_count=Count('id')).filter(record_count__gt=1) # 第二步:筛选出所有属于重复组的记录,对应SQL的JOIN逻辑 duplicate_records = BadReviews.objects.filter( Exists( duplicate_groups.filter( client_id=OuterRef('client_id'), survey_id=OuterRef('survey_id'), text=OuterRef('text'), rating=OuterRef('rating'), privacy_agreement=OuterRef('privacy_agreement') ) ) ).order_by( 'client_id', 'survey_id', 'text', 'rating', 'privacy_agreement', 'id' )
这段ORM代码生成的SQL逻辑和你提供的完全一致:先通过分组统计找出有重复的字段组合,再通过关联筛选出所有属于这些组合的记录,最后按指定字段排序。
2. 扩展:删除重复记录(保留每组中ID最小的条目)
如果最终目的是删除重复记录,只保留每组中ID最小的那条,可以用以下代码:
from django.db.models import Min # 获取每个重复组中需要保留的最小ID keep_ids = BadReviews.objects.values( 'client_id', 'survey_id', 'text', 'rating', 'privacy_agreement' ).annotate(min_record_id=Min('id')).values_list('min_record_id', flat=True) # 删除所有不在保留ID列表中的重复记录 BadReviews.objects.exclude(id__in=keep_ids).delete()
代码说明
values()指定分组字段,和你SQL中的GROUP BY对应;annotate(Count('id'))统计每组的记录数,对应SQL中的COUNT(*);Exists()子查询实现了SQL中的JOIN关联逻辑,确保只匹配完全相同的字段组合;order_by()和你原SQL的排序规则完全一致。
内容的提问来源于stack exchange,提问作者planetp
相关产品推荐
相关产品推荐

