如何查找用户属性的重复项和停用重复项

How to find duplicate and deactivate duplicates for user attributes

假设我们在django中有一个模型定义如下:

class DateClass:
    user_id = models.IntegerField(...)
    sp_date = models.DateField(...)
    is_active = models.BooleanField(...)
    ...

我在这里遵循插入政策,即对于特定用户,只有一个特定的活动日期。这意味着,user=1 在日期 table 对于 sp_date 值 27/10/2021、28/10/2021 等只有一个活动行。对于 user=1,2021 年 10 月 27 日不应有两个活动行,但对于其他用户,2021 年 10 月 27 日不应有两行。每当必须更新日期时,我都会停用 (is_active=False) 前一行并为特定日期添加新行。

我想在一个查询中为每个用户找到重复的活动日期,然后停用(设置 is_active=False)除最后一行(最后插入的行)之外的所有重复值。如果 user_id 和 sp_date 的值相等并且都具有 is_active=True,则两行将重复。我知道如何找到特定列的重复项,这很容易。但我想不出可以优雅地完成上述任务的东西。我只能想到以下方法:

for user in users:
    
    dates = DateClass(user_id=user.id, is_active=True)

    for date in dates:
        days = dates.filter(
            sp_date=date.sp_date, is_active=True
        )
        if days.count() > 1:
            last_day = days.last()
        days.exclude(id=last_day.id).update(is_active=False)

如您所见,上面的方法效率不高,因为我必须遍历所有用户。有没有办法更有效地做到这一点?我正在使用 PostgreSQL 作为数据库。

这个 中的多个重复字段查询集有一个很好的答案,因为我不想占功劳,也不想重新发明轮子,所以我会建议这个答案

对于你的情况应该是:

from django.db.models import Max, Count

duplicate_date_class = DateClass.objects.values('user_id', 'sp_date') \
    .annotate(records=Count('user_id')) \
    .filter(records__gt=1)

# Then do operations on duplicates
for date_class in duplicate_date_class:
    DateClass.objects.filter(
        user_id=date_class['user_id'],
        sp_date=date_class['sp_date']
    )[1:].update(is_active=False)

如果您想避免重复设置多个字段,我建议查看 unique_together 进行模型验证