查找它们所在的行 "similar" 以及在哪些列中
Find rows where they are "similar" and in which columns
我是 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 部分姓氏+部分姓名+出生日期
第三名部分姓氏+部分姓名
姓氏+部分姓名+出生日期+城市第 4
等等...
任何关于如何处理此类查询的想法都将不胜感激,同时考虑到目前我们有固定数量的可能匹配,但将来它们可能会增加(可能会添加更多列,如税号或其他)。
除了 Andrew 的评论之外,您还可以通过对要检查的每一列使用 OR 链接条件的单个自联接来处理它:
ON Col1=Col1
OR Col2=Col2
OR Col3=Col3
etc...
那么您想要的具有匹配类型的额外列将是一个带有 WHEN..THEN 的大型 CASE 表达式,用于您希望在此列中看到的每个可能的组合。
WHEN Col1=Col1 and Col2<>Col2 and Col3<>Col3 THEN 'Col1'
WHEN Col1=Col1 and Col2=Col2 and Col3<>Col3 THEN 'Col1, Col2'
etc...
在上面的示例中,我假设 none 列可以包含 NULL,但如果它们可以,您也必须在逻辑中处理它。
假设表示层是 html 并且您可以在查询输出中使用 html 的位,这是一个粗略的想法,尽管它的工作效率不高并且没有部分匹配,只有精确匹配。要匹配部分,您需要使用 charindex() 或 patindex() 并使用 left() 或 right() 在 ' ' 上拆分,这可能会令人费解。
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) 匹配。
我是 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 部分姓氏+部分姓名+出生日期
第三名部分姓氏+部分姓名
姓氏+部分姓名+出生日期+城市第 4
等等...
任何关于如何处理此类查询的想法都将不胜感激,同时考虑到目前我们有固定数量的可能匹配,但将来它们可能会增加(可能会添加更多列,如税号或其他)。
除了 Andrew 的评论之外,您还可以通过对要检查的每一列使用 OR 链接条件的单个自联接来处理它:
ON Col1=Col1
OR Col2=Col2
OR Col3=Col3
etc...
那么您想要的具有匹配类型的额外列将是一个带有 WHEN..THEN 的大型 CASE 表达式,用于您希望在此列中看到的每个可能的组合。
WHEN Col1=Col1 and Col2<>Col2 and Col3<>Col3 THEN 'Col1'
WHEN Col1=Col1 and Col2=Col2 and Col3<>Col3 THEN 'Col1, Col2'
etc...
在上面的示例中,我假设 none 列可以包含 NULL,但如果它们可以,您也必须在逻辑中处理它。
假设表示层是 html 并且您可以在查询输出中使用 html 的位,这是一个粗略的想法,尽管它的工作效率不高并且没有部分匹配,只有精确匹配。要匹配部分,您需要使用 charindex() 或 patindex() 并使用 left() 或 right() 在 ' ' 上拆分,这可能会令人费解。
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) 匹配。