查找并处理重复的用户

Chr*_*ker 16 mysql sql

在具有以下格式和示例数据的大型用户数据库中,我们正在尝试识别重复的人:

id   first_name    last_name   email
---------------------------------------------------
 1   chris         baker       
 2   chris         baker       chris@gmail.com
 3   chris         baker       chris@hotmail.com
 4   chris         baker       crayzyguy@crazy.com  
 5   carl          castle      castle@npr.org
 6   mike          rotch       fakeuser@sample.com  
Run Code Online (Sandbox Code Playgroud)

我使用以下查询:

SELECT 
    GROUP_CONCAT(id) AS "ids",
    CONCAT(UPPER(first_name), UPPER(last_name)) AS "name",
    COUNT(*) AS "duplicate_count" 
FROM 
    users 
GROUP BY 
    name 
HAVING 
    duplicate_count > 1
Run Code Online (Sandbox Code Playgroud)

这很好用; 我得到一个重复列表,其中包含所涉及行的ID号.

我们会将绑定到副本的任何关联数据重新分配给实际的person(set user_id = 2 where user_id = 3),然后我们删除重复的用户行.

麻烦发生在我们第一次发布此报告之后,因为我们在手动验证它们确实是重复之后清理列表 - 有些不重复.有两个Chris Bakers是合法用户.

我们不希望在随后的重复报告中看到Chris Baker,直到时间结束,所以我正在寻找一种方法来标记用户ID 1和用户ID 4不是彼此重复的未来报告,但他们可以被以后添加的新用户复制.

我尝试了什么

is_not_duplicate在用户表中添加了一个字段,但是如果一个新的副本"Chris Baker"被添加到数据库中,它将导致这种情况不会显示在重复的报告上; 在is_not_duplicate不当排除其中的一个帐户.在有两个重复的Chris Baker加上标记的"真实"之前,我的HAVING陈述不符合> 1门槛is_not_duplicate.

总结的问题

如何在不循环结果或多个查询的情况下在上述查询中构建异常?

子查询很好,但数据集的大小使每个查询都很重要,我希望解决方案尽可能高效.

Hra*_*ian 7

尝试添加is_not_duplicate布尔字段并修改代码,如下所示:

SELECT 
    GROUP_CONCAT(id) AS "ids",
    CONCAT(UPPER(first_name), UPPER(last_name)) AS "name",
    COUNT(*) AS "duplicate_count",
    SUM(is_not_duplicate) AS "real_count"
FROM 
    users 
GROUP BY 
    name 
HAVING 
    duplicate_count > 1
AND
    duplicate_count - real_count > 0
Run Code Online (Sandbox Code Playgroud)

新增副本将is_not_duplicate=0real_count该名称将小于duplicate_count和行会显示