【问题标题】:Remove Records from LEFT JOIN Only If Duplicates and Fits Certain Criteria仅当重复并符合某些条件时才从 LEFT JOIN 中删除记录
【发布时间】:2014-12-12 02:33:23
【问题描述】:

我有一个相当大的文件,在使用 MySQL 将它上传到我的数据库之前,我将它与另一个文件匹配。原始文件约为 211k (t1),与现有数据库 (t2) 匹配后的返回匹配约为 300k——这意味着我必须完成近 90k 的记录删除工作才能上传。

由于第一个使用LEFT JOIN 匹配名称的查询花了很长时间,我将结果保存为一个名为matchnew 的新表(300k 条记录,似乎有 90k 重复或错误匹配)。这是我加入t1t2 后的matchnew 架构示例:

CREATE TABLE `rnmatchnew` (
  `id1` varchar(255) DEFAULT NULL,
  `first1` varchar(255) DEFAULT NULL,
  `last1` varchar(255) DEFAULT NULL,
  `phone1` varchar(255) DEFAULT NULL,
  `zip1` varchar(255) DEFAULT NULL
  `id2` varchar(255) DEFAULT NULL,
  `first2` varchar(255) DEFAULT NULL,
  `last2` varchar(255) DEFAULT NULL,
  `phone2` varchar(255) DEFAULT NULL,
  `zip2` varchar(255) DEFAULT NULL;

(并且两个 ID [id1id2] 不匹配 - 它们是来自两个不同数据库的两个唯一标识符。)

现在我正在使用这个简单的查询来查看大多数重复项或错误匹配项:

SELECT *, COUNT(id1)
FROM matchnew
GROUP BY id1
HAVING COUNT(id1) > 1;

我匹配的每个表都有不同的唯一标识符(第一个表中的id1 和第二个表中的id2,现在两者都存在于matchnew 中)——所以它应该当记录出现​​多次时相当容易看到。另外我因为我离开了将两个现有表连接在一起以获得matchnew,这意味着我从每个表中为每个人都有两组数据——所以两个名字、两个电话号码、两个地址等。但我只做了LEFT JOIN 在名字和姓氏上,以确保我获得最大可能的回报,以确保我不会错过任何人,以防他们搬家或我们有不同的电话号码等。

我的问题是:是否有我可以编写或添加到上述查询的代码,如果行符合特定条件仅当表中有多个唯一 ID 时才会删除行?因此,例如,如果我的id1 是 1234567 并且我上面的查询显示我现在在最后一列中有三个人,我是否可以编写其他代码来删除一两个(但不是全部三个)重复项或如果我的数据与其他限定符(例如电话号码或邮政编码)不匹配,则匹配不正确?

为了进一步澄清,如果我与 id1: 1234567 从最初的 t1 的记录与我的名字从 t2 匹配的三个人 - 有没有办法删除最多两行,如果,例如,来自t1 的记录与来自t2 的三个同名记录之一匹配相同的电话号码? (我指定“最多两个”的唯一原因是因为这个示例有三个重复项——如果它们都不匹配电话号码,我不想完全丢失它们,以防我可以手动做出决定.)

描述起来比我预期的要复杂得多——所以如果我能提供任何进一步的说明,请告诉我!非常感谢您的帮助。

【问题讨论】:

    标签: mysql sql duplicates left-join duplicate-removal


    【解决方案1】:

    您需要先为所有行插入一个标识列

    使用识别列 id ,行将是这样的

    id   id1    phone1   first1
     1   1      732      t1
     2   1      732      t1
     3   1      732      t2
     4   1      891      t3
    

    查询将只删除 id 为 2 的行,因为 id1、phone1、first1 匹配

    我们在 phone1, id1 上进行分组,如果组合有重复值,则只保留 first1 的最大值

    DELETE M FROM matchnew M
    INNER JOIN (
        SELECT id1, phone1, first1, MAX(id) as id
        FROM matchnew
        GROUP BY id1,phone1,first1
        HAVING COUNT(*) > 1 )T
    ON M.id < T.id
    AND M.phone1 = T.phone1
    AND M.id1 = T.id1
    AND M.first1 = T.first1
    

    【讨论】:

    • 谢谢!虽然我不得不承认我不是 100% 确定这是做什么的。我为每一行添加了一个名为id 的连续数字列,这样就完成了。也很抱歉我之前没有很好地分享这个,但id1 看起来更像是随机的 7 位数字,它们都是唯一的,first1 将是每个人的名字。您是否可以进行这些更新并更多地解释您的查询正在做什么?再次感谢您的帮助!
    • @Ryan,这里如果 id1,phone1,first1 相同则只保留 1 行,您可以添加需要用于重复的列,您只能添加 id1,phone1 如果您希望仅基于这两个值保留重复项
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-01
    • 2011-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多