【问题标题】:Django: How to delete duplicate rows based on 2 columns?Django:如何删除基于 2 列的重复行?
【发布时间】:2015-12-17 20:27:10
【问题描述】:

我在this answer 发现我可以使用原始 SQL 轻松删除表中的重复行(基于 N 列的重复)。

是否有使用 Django ORM 的等价物? 我在 Django 中发现的唯一内容仅基于 1 列重复。

注意:我知道有一种方法可以防止 Django 中的未来重复(基于多个字段),使用 unique_together 字段(但我以前不知道)。

谢谢。

【问题讨论】:

  • 可以展示一下表格的一些行和列吗?

标签: python django django-orm


【解决方案1】:

从另一个答案中的 SQL 直接翻译成 Django ORM:

from django.db.models import Min
# First select the min ids
min_id_objects = MyModel.objects.values('A', 'B').annotate(minid=Min('id'))
min_ids = [obj['minid'] for obj in min_id_objects]
# Now delete 
MyModel.objects.exclude(id__in=min_ids).delete()

这将产生 2 个单独的 SQL 查询,而不是另一个答案中提供的一个嵌套 SQL。但我认为这已经足够了。

【讨论】:

  • 如果您的模型有默认排序,请确保通过将 .order_by() 放在末尾来删除它: min_id_objects = MyModel.objects.values('A', 'B').annotate (minid=Min('id')).order_by()。否则,您的默认订单字段将出现在查询的 GROUP BY 子句中,这可能意味着您错过了重复项。
  • @neowang 看来这个查询可能是一个大的 MyModel 数据集和只有几个 dups 的问题,因为由 exclude 创建的 WHERE/IN 子句可能很大。
  • 我发现的一个警告是,如果您想删除创建的第一个对象而不是创建的最后一个对象,请在此处使用 max 而不是 min
【解决方案2】:

您可以在添加唯一性约束的操作之前添加RunSQL operation 以及删除您的一个迁移中的重复项的 SQL。

备注:如果您使用sqlmigrateRunSQL 的优势是将其 SQL 包含到生成的迁移 SQL 中。

【讨论】:

  • 我实际上已经添加了唯一性约束(在删除重复项之前)并应用了迁移。
  • 您可以从数据库中删除所有内容,从添加它的位置删除迁移,添加 RunSQL 并重新创建迁移(我假设它不在生产中)。
猜你喜欢
  • 2016-12-02
  • 2016-04-26
  • 2017-05-24
  • 1970-01-01
  • 2022-01-24
  • 1970-01-01
  • 2023-04-10
  • 1970-01-01
相关资源
最近更新 更多