在具有以下格式和示例数据的大型用户数据库中,我们正在尝试识别重复的人:
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.
总结的问题
如何在不循环结果或多个查询的情况下在上述查询中构建异常?
子查询很好,但数据集的大小使每个查询都很重要,我希望解决方案尽可能高效.
尝试添加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=0让real_count该名称将小于duplicate_count和行会显示