【问题标题】:SQL - Find duplicate fields and count how many fields are matchedSQL - 查找重复字段并计算匹配的字段数
【发布时间】:2014-11-20 17:20:57
【问题描述】:

我有一个大型客户数据库,在某些情况下会多次添加客户,这会导致问题。我可以使用查询来识别完全匹配的记录,尽管有些记录有细微的变化,例如不同的地址或名字。

我想查询 10 个字段,有些记录将匹配所有 10 个字段,这显然是重复的,尽管其他字段可能只匹配 5 个字段与另一条记录,需要进一步调查。因此,我想创建一个结果集,其中包含有多少个字段已匹配的字段。基本上,要创建可能罩的评级,结果是实际匹配。所有 10 个都是明确的重复,但 5 个只是可能的重复。

有些只会匹配 POSTCODE 和 FIRSTNAME,通常可以打折。

这样的事情有帮助,但因为它只返回与所有 3 条记录显式匹配的记录,由于数据量太大,它并不是真正有用。

SELECT field1,field2,field3, count(*)
FROM table_name
GROUP BY field1,field2,field3
HAVING count(*) > 1

【问题讨论】:

  • 有很多方法可以做到这一点。您可以执行常规连接条件,然后为每一列使用 case 表达式。如果 table1.field1 = table2.field2 然后 1 结束...对每一列重复。然后你可以很容易地知道有多少列匹配。
  • 潜在客户群有几千、几百万、??
  • 要明确一点:您希望将每一行与所有其他行进行比较,以确定有多少列是完全匹配的“计数”?你说的是交叉连接(主键不相同,因为它们总是完全匹配),如果有超过一千行左右,这将非常昂贵。
  • @pmbAustin 如果您使用正确的分组集,则不需要交叉连接

标签: sql sql-server count duplicates


【解决方案1】:

你可以试试

Select field1, field2, field3, ... , field10, count(1)
  from customerdatabase
 group by field1, field2, field3, ... , field10
 order by field1, field2, field3, ... , field10

field1 到 field10 按“最可识别/最重要”到最少排序。

【讨论】:

  • 这可能会有所帮助,但我希望创建一个如上所述的查询,该查询使用匹配的字段计数对每个重复项进行评分。由于我们需要定期将数据库提交给监管机构,因此需要在每次提交之前检查表以确保不存在重复。由于它相当大,我们需要确保它尽可能方便用户使用。
【解决方案2】:

这与我想要实现的目标非常接近,它将返回所有包含任何重复字段的记录。我想在结果中添加一列,指示有多少字段与表中的任何其他记录匹配。总共大约有 40,000 条记录。

select * from [CUST].[dbo].[REPORTA] as a
where exists
(select [GIVEN.NAMES],[FAMILY.NAME],[DATE.OF.BIRTH],[POST.CODE],[STREET],[TOWN.COUNTRY]
   from [CUST].[dbo].[REPORTA] as b
   where a.[GIVEN.NAMES] = b.[GIVEN.NAMES]
     or a.[FAMILY.NAME] = b.[FAMILY.NAME]
      or a.[DATE.OF.BIRTH] = b.[DATE.OF.BIRTH]
      or a.[POST.CODE] = b.[POST.CODE]
      or a.[STREET] = b.[STREET]
       or a.[TOWN.COUNTRY] = b.[TOWN.COUNTRY]
   group by [GIVEN.NAMES],[FAMILY.NAME],[DATE.OF.BIRTH],[POST.CODE],[STREET],[TOWN.COUNTRY]
   having count(*) >= 1) 

此查询将返回数千条记录,但我通常对具有大量完全匹配字段的记录感兴趣

【讨论】:

    【解决方案3】:

    您只是缺少CUBE() 的魔力,它会自动生成所有列组合

    DECLARE @duplicate_column_threshold int = 5;
    
    WITH cte AS (
      SELECT
        field1,field2,...,field10
       ,duplicate_column_count = (SELECT COUNT(col) FROM (VALUES (field1),(field2),...,(field10)) c(col))
      FROM table_name
      GROUP BY CUBE(field1,field2,...,field10)
      HAVING COUNT(*) > 1
    )
    SELECT *
    INTO #duplicated_rows
    FROM cte
    WHERE duplicate_column_count >= @duplicate_column_threshold
    

    更新:要从原始表中获取行,请使用在比较列时将 NULL 视为通配符的技术将其与 #duplicated_rows 连接。

    SELECT
      a.* 
     ,b.duplicate_column_count
    FROM table_name a 
    INNER JOIN #duplicated_rows b
      ON  NULLIF(b.field1,a.field1) IS NULL
      AND NULLIF(b.field2,a.field2) IS NULL
      ...
      AND NULLIF(b.field10,a.field10) IS NULL
    

    【讨论】:

    • 感谢 Anon,它运行良好,我能够达到预期的效果。
    • 是否可以返回在上述查询中匹配的客户 ID 字段。客户 ID 始终是唯一的,也有助于返回这些值。
    • 感谢 Anon,这有帮助。当我使用 intersect 运行查询时,它需要一段时间,我让它运行,1.5 小时后它返回一些结果,但仍在运行,所以我停止了。我也丢失了 duplicate_column_count 有没有办法在结果中保留它。
    • 但是你已经回答了我原来的问题,所以感谢你分享你的知识。我现在可以返回包含重复字段数的结果。返回附加字段会很有用,但在这个阶段很好。
    • 再次更新以避免INTERSECT
    猜你喜欢
    • 2021-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多