【问题标题】:Querying database to find potential duplicates based on multiple columns查询数据库以查找基于多列的潜在重复项
【发布时间】:2017-07-25 15:09:19
【问题描述】:

我的数据库中有一个表,其中有大约 10 万个客户,并且有一个错误的系统已经存在了很长一段时间,我们才发现我们可能有成千上万的重复记录,这不应该有被重复了。

这是表格的基本结构...

ClientID         FName           LName           DOB          SysEMID
----------------------------------------------------------------------
123              Janette         Marukan         1/2/1990     111111S
478              Jannete         Maruckan        1/2/1990     111111S

这些不是系统中的所有字段,但我的目标是能够在我的搜索查询中使用上面的列。因此,我尝试获取名字和姓氏、DOB 以及 SysEMID 的前 2 或 3 个字母,并查找所有可能重复的记录。

从上表中可以看出我有两个客户端,但它们的名称略有不同——实际上这两个客户端都是相同的,但它们在系统中保存为两个。有没有办法让我以某种方式查询整个表并找到它?

我真的没有 1 个特定的客户 - 它更像是一种通用的查询,向我展示具有相同 2 或 3 个字母的 1st Name、Last Name 和 DOB 的潜在客户重复项?

【问题讨论】:

  • 为什么不简单地做一个ORDER BY SUBSTRING()?长度为 3 的初学者
  • DOB 字段相隔 10 年。这些真的是同一个客户吗?
  • @GordonLinoff - 是的,它们应该是一样的。抱歉……我只是抄袭

标签: sql sql-server


【解决方案1】:

你会使用窗口函数:

select t
from (select t.*,
             count(*) over (partition by left(fname, 2), left(lname, 2), dob, sysemid) as cnt
      from t
     ) t
where cnt > 1
order by sysemid, dob, fname, lname;

这也可能是soundex() 真正有用的少数情况之一。毕竟,它的设计考虑了字符串。所以:

select t
from (select t.*,
             count(*) over (partition by soundex(fname), soundex(lname), dob, sysemid) as cnt
      from t
     ) t
where cnt > 1
order by sysemid, dob, fname, lname;

【讨论】:

  • 任何方式我基本上可以通过名字和姓氏的前 2 或 3 个字母和 DOB 进行搜索,让它们按名字和姓氏组织,这样我就可以将数据复制到 excel 中并从那里去。仅向我显示 >1 条记录需要我调查每个 DOB,但如果我能够看到所有这些,这样我就可以跳过并知道哪些是重复的,哪些不是。我猜是远射。谢谢。
【解决方案2】:

我猜您已经解决了新数据的问题,但对于旧数据,您可以执行以下操作:

1) 进行精确比较,以获得非常精确的副本。这是最简单的部分。

2) 对于类似的字符串,例如 Josh 和 Joshh,您需要使用一些您需要编写的代码来检查两个字符串之间的距离,或者如果您只喜欢使用 SQL 编码,那么更简单的方法是使用 DIFFERENCE 函数。这将为您提供 0-4 的值,其中 4 表示字符串非常相似。这样做的坏处是您需要快速查看它们以确保一切正常。欲了解更多信息https://technet.microsoft.com/en-us/library/ms189282(v=sql.105).aspx

3)我更喜欢你去,打开Visual Studio或者你喜欢的IDE,连接你的数据库,选择表中的全部数据,把它带入内存,实现一个很好的字符串距离函数。

【讨论】:

  • 不一定要精确我猜如果我能以某种方式使用 DOB 作为我的主要标识符会起作用,因为这会显着减少列表。基本上是寻找重复 DOB 的名字和姓氏的类似子字符串。有人只是需要这个作为参考,基本上是为了看看客户是否可能拥有所有相同的信息,但名字中的字母不同,如上例所示。
【解决方案3】:

像这样:

SELECT LEFT(FName,2) AS FN, LEFT(LName,2) AS LN, DOB, COUNT(*)
FROM YourTable
GROUP BY LEFT(FName,2), LEFT(LName,2), DOB
HAVING COUNT(*) > 1
;

【讨论】:

  • 谢谢 - 这无疑大大缩小了范围。
【解决方案4】:

SQL Server 中没有内置的灵丹妙药。您必须决定您的业务规则并对其进行编码。

例如,如果您决定在名称的前 3 个字母中查找匹配项,请使用 LEFT() 函数来获取前 3 个字母。要查看 DOB 的各个部分,可以使用 DATEPART() 函数。

【讨论】:

猜你喜欢
  • 2019-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-25
  • 2014-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多