SQL查询查找精确和近似重复

SQL查询查找精确和近似重复,sql,sql-server,duplicates,similarity,fuzzy-comparison,Sql,Sql Server,Duplicates,Similarity,Fuzzy Comparison,我有一个包含FirstName、LastName、Add1和其他字段的SQL表。我正在努力清理这些数据。有一些可能被欺骗的例子- 超过1条记录的所有3列都完全相同 第一个和最后一个是相同的,只有1有一个地址,另一个是空的 第一个和最后一个类似(John | Doe与John C.| Doe),地址相同或一个为空 我想生成一个查询,我可以提供给用户,这样他们可以检查这些记录,比较他们的相关记录,然后删除他们不需要的记录 我一直在研究相似性函数、soundex等等,但这一切似乎都很复杂。有没有一个简

我有一个包含FirstName、LastName、Add1和其他字段的SQL表。我正在努力清理这些数据。有一些可能被欺骗的例子-

  • 超过1条记录的所有3列都完全相同
  • 第一个和最后一个是相同的,只有1有一个地址,另一个是空的
  • 第一个和最后一个类似(John | Doe与John C.| Doe),地址相同或一个为空
  • 我想生成一个查询,我可以提供给用户,这样他们可以检查这些记录,比较他们的相关记录,然后删除他们不需要的记录

    我一直在研究相似性函数、soundex等等,但这一切似乎都很复杂。有没有一个简单的方法可以做到这一点

    谢谢


    编辑:

    下面是一些示例数据:

    FirstName    |   LastName    |      Add1
    John         |   Doe         |   1 Main St
    John         |   Doe         |   
    John A.      |   Doe         |   
    Jane         |   Doe         |   2 Union Ave
    Jane B.      |   Doe         |   2 Union Ave
    Alex         |   Smith       |   3 Broad St
    Chris        |   Anderson    |   4 South Blvd
    Chris        |   Anderson    |   4 South Blvd
    
    我真的很喜欢Critical Error的查询来识别所有不同类型的复制品。这将给我上面的样本数据,不包括Alex Smith的结果,因为没有重复

    我想做的是获取结果集并确定哪些是Jane Doe的复制品。她应该只有两次。约翰·多伊有3个,克里斯·安德森有2个。我能得到那个子结果集吗


    编辑:

    我知道了!我将把关键错误的答案标记为解决方案,因为它完全让我达到了我需要去的地方。这是解决方案,以防对其他人有所帮助。基本上,这就是我们正在做的

  • 从存在重复项的表中选择记录
  • 添加WHERE EXISTS子查询以在同一个表中查找确切的重复项,其中主查询和子查询的ID不匹配
  • 添加WHERE EXISTS子查询以在相同的表中查找类似的重复项,使用重复列之间的差异因子,其中主查询和子查询的ID不匹配
  • 添加WHERE EXISTS子查询以在同一表中查找两个字段上的重复项,其中第三个字段可能为空,用于其中一条记录,其中主查询和子查询的ID不匹配
  • 每个子查询都与OR连接,因此可以找到任何类型的重复项
  • 在每个子查询的末尾添加一个嵌套的要求,即主查询或子查询都是要识别重复项的记录的ID
  • 将@CID声明为INT
    将ANSI_空值设置为ON
    不计数;
    设置为@CID=12345
    开始
    挑选
    *
    来自@c客户
    哪里
    --完全相同。
    存在(
    从@Customers x中选择*
    x、 FirstName=c.FirstName
    和x.LastName=c.LastName
    x.Add1=c.Add1
    和x.Id c.Id
    和(x.ID=@CID或c.ID=@CID)
    )
    --匹配名/姓相同/相似,地址相同。
    还是存在(
    从@Customers x中选择*
    差异(x.FirstName,c.FirstName)=4
    和差(x.LastName,c.LastName)=4
    x.Add1=c.Add1
    和x.Id c.Id
    和(x.ID=@CID或c.ID=@CID)
    )
    --匹配名/姓,并且存在一个地址。
    还是存在(
    从@Customers x中选择*
    x、 FirstName=c.FirstName
    和x.LastName=c.LastName
    和x.Id c.Id
    及(
    x、 Add1为NULL,c.Add1不为NULL
    或
    x、 Add1不为NULL,c.Add1为NULL
    )
    和(x.ID=@CID或c.ID=@CID)
    );
    
    假设记录之间有唯一的id,您可以尝试一下:

    DECLARE @Customers table ( FirstName varchar(50), LastName varchar(50), Add1 varchar(50), Id int IDENTITY(1,1) );
    INSERT INTO @Customers ( FirstName, LastName, Add1 ) VALUES
        ( 'John', 'Doe', '123 Anywhere Ln' ),
        ( 'John', 'Doe', '123 Anywhere Ln' ),
        ( 'John', 'Doe', NULL ),
        ( 'John C.', 'Doe', '123 Anywhere Ln' ),
        ( 'John C.', 'Doe', '15673 SW Liar Dr' );
    
    SELECT
        *
    FROM @Customers c
    WHERE
        -- Exact duplicates.
        EXISTS (
    
            SELECT * FROM @Customers x WHERE
                x.FirstName = c.FirstName 
                AND x.LastName = c.LastName 
                AND x.Add1 = c.Add1 
                AND x.Id <> c.Id
        
        )
        -- Match First/Last name are same/similar and the address is same.
        OR EXISTS (
        
            SELECT * FROM @Customers x WHERE
                DIFFERENCE( x.FirstName, c.FirstName ) = 4 
                AND DIFFERENCE( x.LastName, c.LastName ) = 4
                AND x.Add1 = c.Add1
                AND x.Id <> c.Id
    
        )
        -- Match First/Last name and one address exists.
        OR EXISTS (
        
            SELECT * FROM @Customers x WHERE
                x.FirstName = c.FirstName 
                AND x.LastName = c.LastName
                AND x.Id <> c.Id
                AND (
                    x.Add1 IS NULL AND c.Add1 IS NOT NULL
                    OR
                    x.Add1 IS NOT NULL AND c.Add1 IS NULL
                )
        );
    
    初始结果集:

    +-----------+----------+------------------+----+
    | FirstName | LastName |       Add1       | Id |
    +-----------+----------+------------------+----+
    | John      | Doe      | 123 Anywhere Ln  |  1 |
    | John      | Doe      | 123 Anywhere Ln  |  2 |
    | John      | Doe      | NULL             |  3 |
    | John C.   | Doe      | 123 Anywhere Ln  |  4 |
    | John C.   | Doe      | 15673 SW Liar Dr |  5 |
    +-----------+----------+------------------+----+
    

    假设记录之间有唯一的id,您可以尝试一下:

    DECLARE @Customers table ( FirstName varchar(50), LastName varchar(50), Add1 varchar(50), Id int IDENTITY(1,1) );
    INSERT INTO @Customers ( FirstName, LastName, Add1 ) VALUES
        ( 'John', 'Doe', '123 Anywhere Ln' ),
        ( 'John', 'Doe', '123 Anywhere Ln' ),
        ( 'John', 'Doe', NULL ),
        ( 'John C.', 'Doe', '123 Anywhere Ln' ),
        ( 'John C.', 'Doe', '15673 SW Liar Dr' );
    
    SELECT
        *
    FROM @Customers c
    WHERE
        -- Exact duplicates.
        EXISTS (
    
            SELECT * FROM @Customers x WHERE
                x.FirstName = c.FirstName 
                AND x.LastName = c.LastName 
                AND x.Add1 = c.Add1 
                AND x.Id <> c.Id
        
        )
        -- Match First/Last name are same/similar and the address is same.
        OR EXISTS (
        
            SELECT * FROM @Customers x WHERE
                DIFFERENCE( x.FirstName, c.FirstName ) = 4 
                AND DIFFERENCE( x.LastName, c.LastName ) = 4
                AND x.Add1 = c.Add1
                AND x.Id <> c.Id
    
        )
        -- Match First/Last name and one address exists.
        OR EXISTS (
        
            SELECT * FROM @Customers x WHERE
                x.FirstName = c.FirstName 
                AND x.LastName = c.LastName
                AND x.Id <> c.Id
                AND (
                    x.Add1 IS NULL AND c.Add1 IS NOT NULL
                    OR
                    x.Add1 IS NOT NULL AND c.Add1 IS NULL
                )
        );
    
    初始结果集:

    +-----------+----------+------------------+----+
    | FirstName | LastName |       Add1       | Id |
    +-----------+----------+------------------+----+
    | John      | Doe      | 123 Anywhere Ln  |  1 |
    | John      | Doe      | 123 Anywhere Ln  |  2 |
    | John      | Doe      | NULL             |  3 |
    | John C.   | Doe      | 123 Anywhere Ln  |  4 |
    | John C.   | Doe      | 15673 SW Liar Dr |  5 |
    +-----------+----------+------------------+----+
    

    请提供样本数据和预期结果。您想要做的事情还不清楚。只需按名字、名字、地址1和HAVING COUNT(*)>1进行分组,就可以解决第一种情况,第二种情况类似,第三种情况我敢打赌,在您的表中,您有一个更适合查找重复项的指示字段,而不仅仅是“类似名称”,有些人的名字可能相同,但这并不意味着他们是同一个人……请提供样本数据和期望的结果。您想要做的事情还不清楚。只需按名字、名字、地址1和HAVING COUNT(*)>1进行分组,就可以解决第一种情况,第二种情况类似,第三种情况我敢打赌,在您的表中,您有一个更适合查找重复项的指示字段,而不仅仅是“类似名称”,有些人的名字是一样的,但这并不意味着他们是同一个人……这太棒了!非常感谢。我现在要试着把这些放在一起,看看结果如何。我会发回的,一旦我这样做了。这太棒了!非常感谢。我现在要试着把这些放在一起,看看结果如何。我会发回的,一旦我发了。