【问题标题】:Django ORM. Select only duplicated fields from DBDjango ORM。仅从数据库中选择重复的字段
【发布时间】:2020-08-03 01:42:40
【问题描述】:

我在数据库中有这样的表:

MyTableWithValues
id | user(fk to Users) | value(fk to Values) |   text     | something1 | something2 ...
1  | userobject1       | valueobject1        |asdasdasdasd| 123        | 12321
2  | userobject2       | valueobject50       |QWQWQWQWQWQW| 515        | 5555455
3  | userobject1       | valueobject1        |asdasdasdasd| 12345      | 123213

我需要删除所有重复字段 user、valuetext 的对象,但要从中保存一个。在本例中将删除第 3 条记录。

如何使用 Django ORM 做到这一点?

PS: 试试这个:

recs = (
        MyTableWithValues.objects
        .order_by()
        .annotate(max_id=Max('id'), count_id=Count('user__id'))
        #.filter(count_id__gt=1)
        .annotate(count_values=Count('values'))
        #.filter(count_icd__gt=1)
)
    ...
    ...
    for r in recs:
        print(r.id, r.count_id, , r.count_values)

它会打印如下内容:

1 1 1
2 1 1
3 1 1
...

尽管数据库中存在重复值这一事实。我不明白,为什么 Count 功能不起作用。

谁能帮帮我?

【问题讨论】:

    标签: django python-3.x django-orm


    【解决方案1】:

    您应该首先了解 count 的工作原理。 Count 方法将计算相同的行。 它使用对象中所有可用的字段来检查它是否与其他行的字段相同。 因此,在当前情况下,count_values 的结果为 1,因为 Count 正在使用除 id 之外的所有字段来查找相似的行。 Count 包括 user,value,text,something1,something2 字段以检查相似性。

    要计算具有相似字段的行,您必须仅使用用户、值和文本字段

    查询:

      recs = MyTableWithValues.objects
             .values('user','values','text')
             .annotate(max_id=Max('id'),count_id=Count('user__id'))
             .annotate(count_values=Count('values'))
    

    它会返回一个字典列表

      print(recs)
    

    输出:

    <QuerySet[{'user':1,'values':1,'text':'asdasdasdasd','max_id':3,'count_id':2,'count_values':2},{'user':2,'values':2,'text':'QWQWQWQWQWQW','max_id':2,'count_id':1,'count_values':1}]
    

    使用此查询集,您可以检查包含多少次具有相同值的用户、值和文本字段

    【讨论】:

      【解决方案2】:

      Python 循环对你有用吗?

      import collections
      
      d = collections.defaultdict(list)
      
      # group all objects by the key
      for e in MyTableWithValues.objects.all():
          k = (e.user_id, e.value_id, e.text)
          d[k].append(e)
      
      for k, obj_list in d.items():
          if len(obj_list) > 1:
              for e in obj_list[1:]:
                  # except the first one, delete all objects
                  e.delete()
      

      【讨论】:

      • 我可以使用它,但数据库查询的工作速度比 python 代码快得多。我有数千个值的数据库,我需要一个高速代码:)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-05-06
      • 2014-08-26
      • 2014-03-16
      • 2021-01-03
      • 1970-01-01
      • 2014-01-20
      • 2014-11-12
      相关资源
      最近更新 更多