如何查找用户属性的重复项和停用重复项
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 进行模型验证
假设我们在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 进行模型验证