我有一个有趣的问题,我的逻辑不能胜任这个任务。
我们有一个表,有时会产生重复记录(出于过程原因,这是不可避免的)。请看以下示例:
id FirstName LastName PhoneNumber email
-- --------- -------- ------------ --------------
1 John Doe 123-555-1234 jdoe@gmail.com
2 Jane Smith 123-555-1111 jsmith@foo.com
3 John Doe 123-555-4321 jdoe@yahoo.com
4 Bob Jones 123-555-5555 bob@bar.com
5 John Doe 123-555-0000 jdoe@hotmail.com
6 Mike Roberts 123-555-9999 roberts@baz.com
7 John Doe 123-555-1717 wally@domain.com
我们通过这种方式找到重复的内容:
SELECT c1.*
FROM `clients` c1
INNER JOIN (
SELECT `FirstName`, `LastName`, COUNT(*)
FROM `clients`
GROUP BY `FirstName`, `LastName`
HAVING COUNT(*) > 1
) AS c2
ON c1.`FirstName` = c2.`FirstName`
AND c1.`LastName` = c2.`LastName`
这将生成以下重复列表:
id FirstName LastName PhoneNumber email
-- --------- -------- ------------ --------------
1 John Doe 123-555-1234 jdoe@gmail.com
3 John Doe 123-555-4321 jdoe@yahoo.com
5 John Doe 123-555-0000 jdoe@hotmail.com
7 John Doe 123-555-1717 wally@domain.com
如您所见,基于FirstName
和LastName
,所有记录都是重复的。
此时,我们实际上打电话给客户以清除可能的重复项。
在这样做之后,我们学习(例如)记录1和3是真实的重复,但记录5和7实际上是两个不同的人。
因此,我们将记录1和3中任何无关链接的数据合并到记录1中,删除记录3,并单独留下记录5和7。
现在出现了问题:
下次我们重新运行“重复”查询时,它将包含以下行:
id FirstName LastName PhoneNumber email
-- --------- -------- ------------ --------------
1 John Doe 123-555-4321 jdoe@gmail.com
5 John Doe 123-555-0000 jdoe@hotmail.com
7 John Doe 123-555-1717 wally@domain.com
它们似乎都是重复的,即使我们之前已经认识到它们不是。
您如何确定这些记录不重复?
我的第一个虽然建立一个查找表来识别哪些记录不是彼此重复的(例如,{1,5},{1,7},{5,7}),但我不知道如何构建一个能够使用这些数据的查询。
此外,如果显示另一个重复记录,则可能是1,5或7的副本,因此我们需要将它们全部显示在重复列表中,以便客户服务人员可以呼叫该人员。新记录,以找出他可能是重复的记录。
我试图理解这一点,我已经达到了极限。那里有哪些才华横溢的天才会对此有所了解?
答案 0 :(得分:1)
有趣的问题。这是我对它的抨击。
如果我们从略微不同的角度处理问题怎么样呢。
考虑到系统一开始是干净的,即系统中当前所有记录都是使用唯一的第一个和最后一个名字组合,或者相同的第一个和最后一个名称已被手动确认为不同的人。
在系统中输入新用户时,我们会进行额外检查。可以实现为INSERT触发器,也可以仅在成功完成插入后调用另一个过程。
从SQL的角度来看,
TABLE MatchingTable
COLUMNS 1. NewUserID 2. ExistingUserID
Constraint : Logical PK = NewUserID + ExistingMatchingRecordsUserID
INSERT INTO MATCHINGTABLE VALUES ('NewUserId', userId)
SELECT userId FROM User u where u.firstName = 'John' and u.LastName = 'Doe'
MatchingTable中的所有条目都需要解析。
当管理员登录系统时,管理员会看到MatchingTable中所有条目的列表
例如:新用户John Doe - (ID 345) - 3个潜在匹配John Doe - ID 123 ID 231 / ID 256
管理员将根据123/231和256中的数据检查345的数据,并手动确认是否重复ANY / None 如果Duplicate,则从用户表中删除345(软/硬删除 - 适合您的任何内容) 如果不是,ID 354的条目只是从MatchingTable中删除(我会在这里使用硬删除,因为这就像一个事务临时表,但一切都很好)。
此外,当从MatchingTable中删除ID 354的条目时,将自动删除MatchingTable中ExistingMatchingRecordsUserID = 354的所有其他条目,以确保不需要对已经验证的数据进行不必要的手动验证。
同样,这可能是一个潜在的DELETE触发/ Just逻辑另外在DELETE of MatchingTable上执行。实施受到优先考虑。
答案 1 :(得分:0)
以每行向表格添加单个字节为代价,您可以添加manually_verified BOOL
列,默认值为FALSE
。如果您手动验证了数据,请将其设置为TRUE
。然后,您只需查询manually_verified = FALSE
。
它简单,有效,并且与业务流程中实际发生的事情相匹配:您手动验证数据。
如果您想更进一步,可能需要在验证行时进行存储并验证谁。由于存储在主表中可能很烦人,因此您当然可以将其存储在单独的表中,并在验证数据中存储LEFT JOIN
。您甚至可以创建一个视图来重新创建单个主表的外观。
要解决添加新重复的问题:您将针对整个数据集检查未经验证的数据。这意味着您的主表c1
的条件为manually_verified = FALSE
,但您的INNER JOIN
ed表c2
却没有。这样,未经验证的数据仍将找到所有可能的重复匹配:
SELECT * FROM table t1
INNER JOIN table t2 ON t1.name = t2.name AND t1.id <> t2.id
WHERE t1.manually_verified = FALSE
重复项的可能匹配项将在联接表中。