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

时间:2019-03-01 15:02:22

标签: tsql sql-server-2017

我对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  ║
╚═════════════╩═══════════════╩══════════════╩════════╝

例如:
第一行与姓,名+出生日期匹配
姓氏部分+名字部分+出生日期第二名
姓氏部分+姓名部分第三名
姓氏+名字部分+出生日期+城市第四名
等等...

考虑到目前我们具有固定数量的可能匹配项,但考虑到将来可能会增加(可能增加诸如“税号”之类的其他列)的任何想法,我们将不胜感激。 >

2 个答案:

答案 0 :(得分: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,但是如果可以的话,您也必须在逻辑中进行处理。

答案 1 :(得分:0)

假设表示层是html,并且您可以在查询输出中使用html一点,这是一个粗略的主意,尽管工作并不精确有效,也没有部分匹配,只是精确。要匹配部分,您将需要使用charindex()或patindex()并用left()或right()对''进行拆分,这会令人费解。

一个左右单词拆分的方式,至少是我仍然拆分的方式。

--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()值来获得越来越广泛的匹配,但是如果您转到left(soundex(name),1)匹配项,那么您将得到所有以第一个字母开头的名称。