查找它们“相似”的行以及哪些列

问题描述 投票:0回答:2

我是SQL Server(2017)的新手,我有这样的需求: 考虑这个记录:

╔═════════════╦═══════════════╦══════════════╦═══════╗
║   Surname   ║     Name      ║ Day of birth ║ City  ║
╠═════════════╬═══════════════╬══════════════╬═══════╣
║ Rivers Lara ║ Wanda Leticia ║ 07/04/1956   ║ Paris ║
╚═════════════╩═══════════════╩══════════════╩═══════╝

我将在下面的列表中找到所有匹配的记录,突出显示匹配的类型:

╔═════════════╦═══════════════╦══════════════╦════════╗
║   Surname   ║     Name      ║ Day of birth ║  City  ║
╠═════════════╬═══════════════╬══════════════╬════════╣
║ Rivers Lara ║ Wanda Leticia ║ 07/04/1956   ║ London ║
║ Rivers      ║ Leticia       ║ 07/04/1956   ║ Rome   ║
║ Rivers      ║ Leticia       ║ 14/03/1995   ║ Rome   ║
║ Rivers Lara ║ Leticia       ║ 07/04/1956   ║ Paris  ║
║ Rivers Lara ║ Wanda Leticia ║ 08/07/1983   ║ Paris  ║
╚═════════════╩═══════════════╩══════════════╩════════╝

例如: 第一行匹配姓氏+姓名+ dayofbirth 姓氏的第2名+姓名的一部分+ dayofbirth 姓氏的一部分+姓名的一部分 姓氏第4名+名称+日产+城市的一部分 等等...

关于如何处理这种类型的查询的任何想法都将受到赞赏,同时考虑到目前我们有可能匹配的固定数量,但在将来它们可能会增加(可能会添加更多列,如税号或其他)。

tsql sql-server-2017
2个回答
0
投票

假设表示层是html,并且你在查询输出中使用了一些html,这是一个粗略的想法,虽然它不是精确有效而且没有部分匹配,只是精确。要匹配部分你需要使用charindex()或patindex()并拆分''与左()或右(),可以得到复杂。

左/右单词的一个分割是这样的,至少这是我分裂的方式。

--this is only an example on the convoluted nature of string manipulation.
declare @Surname varchar(128) = 'Rivers Lara';
select 
     rtrim(iif(charindex(' ',@Surname) = 0,@Surname,Left(@Surname, charindex(' ',@Surname)))) first_part_Surname
    ,ltrim(reverse(iif(charindex(' ',@Surname) = 0,reverse(@Surname),Left(reverse(@Surname), charindex(' ',reverse(@Surname)))))) last_part_Surname
declare @StartRed varchar(50) = '<span style="color: red;">'
       ,@StopRed varchar(50) = '</span>';
select 
     case when tm.Surname = tr.Surname then @StartRed + tr.Surname + @StopRed else tr.Surname end Surname
    ,case when tm.Name = tr.Name then @StartRed + tr.Name  + @StopRed else tr.Name end [Name]
    ,case when tm.[Day of Birth] = tr.[Day of Birth] then @StartRed + convert(varchar, tr.[Day of Birth], 1) + @StopRed end [Day of Birth]
    ,case when tm.City = tr.City then @StartRed + tr.City + @StopRed else tr.City end City
from TableMatch tm
inner join TableRecords tr on (tm.Surname = tr.Surname or tm.Name = tr.Name) 
    and (tm.[Day of Birth] = tr.[Day of Birth] or tm.City = tr.City)

-- requires either Surname or Name to match and at least 1 of the 2 others to match

此外,您可以使用soundex()找到听起来像其他名称的名称作为一个没有任何操纵的止损。你也可以使用left()soundex()值来获得更广泛和更广泛的匹配,但是如果你向左转(soundex(name),1)匹配,你最终会得到所有以第一个字母开头的名字。


0
投票

除了Andrew的评论之外,您还可以通过一个自我联接来处理它,并为要检查的每个列添加OR链接条件:

ON Col1=Col1
OR Col2=Col2
OR Col3=Col3
etc...

那么你需要的额外列与匹配类型将是一个大型的CASE表达式,其中包含WHEN..THEN,用于您希望在此列中看到的每种可能的组合。

WHEN Col1=Col1 and Col2<>Col2 and Col3<>Col3 THEN 'Col1'
WHEN Col1=Col1 and Col2=Col2 and Col3<>Col3 THEN 'Col1, Col2'
etc...

在上面的例子中,我假设没有列可以包含NULL,但如果它们可以,你也必须在逻辑中处理它。

© www.soinside.com 2019 - 2024. All rights reserved.