我有 2 个包含许多列的表,我想找到 table1.somecolumn 中的值包含在 table2.someothercolumn 中的那些行。示例:
表 1.somecolumn 有 Smith、Peter 和
table2.someothercolumn 有 peter.smith
那应该是匹配的,我该如何进行这样的搜索?
您可以尝试使用
SOUNDEX
或 DIFFERENCE
函数来帮助匹配字符串文字。
示例:
select difference('peter.green', 'Green, Peter')
返回
2
,其中:
返回的整数是个数 SOUNDEX 值中的字符 是相同的。返回值范围 从 0 到 4:0 表示弱或 没有相似性,4表示强 相似或相同的值。
请参阅 MSDN 上的 SOUNDEX 和 DIFFERENCE 主题。
更新:
当考虑单词顺序时,Soundex & Difference 可能无法正常工作,但如果您安装了全文索引功能,则无需创建索引即可使用全文引擎的分词和解析功能。假设您使用的是 SQL Server 2008,以下函数将返回规范化术语的列表:
SELECT * FROM sys.dm_fts_parser('"Peter Green"', 1033, 0, 0)
通过它您可以
CROSS APPLY
完成查询的其余部分。
请参阅 sys.dm_fts_parser 主题和 K 部分。在 FROM 主题中使用应用以了解更多信息。
示例:(启用了全文引擎的 SQL Server Enterprise 2008)
if not OBJECT_ID('Names1', 'Table') is null drop table names1
if not OBJECT_ID('Names2', 'Table') is null drop table names2
create table Names1
(
id int identity(0, 1),
name nvarchar(128)
)
insert into Names1 (name) values ('Green, Peter')
insert into Names1 (name) values ('Smith, Peter')
insert into Names1 (name) values ('Aadland, Beverly')
insert into Names1 (name) values ('Aalda, Mariann')
insert into Names1 (name) values ('Aaliyah')
insert into Names1 (name) values ('Aames, Angela')
insert into Names1 (name) values ('Aames, Willie')
insert into Names1 (name) values ('Aaron, Caroline')
insert into Names1 (name) values ('Aaron, Quinton')
insert into Names1 (name) values ('Aaron, Victor')
insert into Names1 (name) values ('Abbay, Peter')
insert into Names1 (name) values ('Abbott, Dorothy')
insert into Names1 (name) values ('Abbott, Bruce')
insert into Names1 (name) values ('Abbott, Bud')
insert into Names1 (name) values ('Abbott, Philip')
insert into Names1 (name) values ('Abdoo, Rose')
insert into Names1 (name) values ('Abdul, Paula')
insert into Names1 (name) values ('Abel, Jake')
insert into Names1 (name) values ('Abel, Walter')
insert into Names1 (name) values ('Abeles, Edward')
insert into Names1 (name) values ('Abell, Tim')
insert into Names1 (name) values ('Aber, Chuck')
create table Names2
(
id int identity(200, 1),
name nvarchar(128)
)
insert into Names2 (name) values (LOWER('Peter.Green'))
insert into Names2 (name) values (LOWER('Peter.Smith'))
insert into names2 (name) values (LOWER('Beverly.Aadland'))
insert into names2 (name) values (LOWER('Mariann.Aalda'))
insert into names2 (name) values (LOWER('Aaliyah'))
insert into names2 (name) values (LOWER('Angela.Aames'))
insert into names2 (name) values (LOWER('Willie.Aames'))
insert into names2 (name) values (LOWER('Caroline.Aaron'))
insert into names2 (name) values (LOWER('Quinton.Aaron'))
insert into names2 (name) values (LOWER('Victor.Aaron'))
insert into names2 (name) values (LOWER('Peter.Abbay'))
insert into names2 (name) values (LOWER('Dorothy.Abbott'))
insert into names2 (name) values (LOWER('Bruce.Abbott'))
insert into names2 (name) values (LOWER('Bud.Abbott'))
insert into names2 (name) values (LOWER('Philip.Abbott'))
insert into names2 (name) values (LOWER('Rose.Abdoo'))
insert into names2 (name) values (LOWER('Paula.Abdul'))
insert into names2 (name) values (LOWER('Jake.Abel'))
insert into names2 (name) values (LOWER('Walter.Abel'))
insert into names2 (name) values (LOWER('Edward.Abeles'))
insert into names2 (name) values (LOWER('Tim.Abell'))
insert into names2 (name) values (LOWER('Chuck.Aber'));
with ftsNamesFirst (id, term) as
(
select id, terms.display_term
from names1 cross apply sys.dm_fts_parser('"' + name + '"', 1033, 0, 0) terms
), ftsNamesSecond (id, term) as
(
select id, terms.display_term
from names2 cross apply sys.dm_fts_parser('"' + name + '"', 1033, 0, 0) terms
)
select * from
(
select
ROW_NUMBER() over (partition by nfirst.id order by sum(DIFFERENCE(ftsNamesFirst.term, ftsNamesSecond.term)) desc) ranking,
sum(DIFFERENCE(ftsNamesFirst.term, ftsNamesSecond.term)) Confidence,
nFirst.id Names1ID,
nFirst.name Names1Name,
nSecond.id Names2ID,
nSecond.name Names2Name
from
ftsNamesFirst cross join ftsNamesSecond
left outer join names1 nFirst on nFirst.id = ftsNamesFirst.id
left outer join names2 nSecond on nSecond.id = ftsNamesSecond.id
where DIFFERENCE(ftsNamesFirst.term, ftsNamesSecond.term) = 4
group by
nFirst.id, nFirst.name, nSecond.id, nSecond.name
) MatchedNames
where ranking = 1
输出:
置信度最高的匹配优先(使用窗口排名查询过滤掉所有其他匹配)。
Confidence Names1ID Names1Name Names2ID Names2Name
8 0 Green, Peter 200 peter.green
8 1 Smith, Peter 201 peter.smith
8 2 Aadland, Beverly 202 beverly.aadland
8 3 Aalda, Mariann 203 mariann.aalda
4 4 Aaliyah 204 aaliyah
8 5 Aames, Angela 205 angela.aames
8 6 Aames, Willie 206 willie.aames
它并不完美,但这是一个很好的起点,可以对其进行调整以提供更高的成功概率。
有多种可能的解决方案,具体取决于您的需求: 使用可以创建辅助表来存储每条记录的关键字
如果它遵循严格的模式,以便名称之间始终有逗号和空格,您还可以按逗号和空格分割字符串,请参阅STRING_SPLIT (Transact-SQL)。
“史密斯,彼得”上的string_split()
和 ID
列将变为:
ID String
1 Smith
1
1 Peter
然后使用
select somestring like '%'+someotherstring+'%'
(以及 lower
所有字符串)检查一个 String
的所有 ID
: 是否可以在另一表的列中的某处找到。
我不会花时间进一步检查这一点,但您可以逐步到达那里。我认为这不是一个有用的答案,因为您应该使用 SSIS 中的模糊逻辑或 SSIS 的其他(外部)组件等工具来检查模糊名称。还要搜索存储过程。并检查是否可以使用另一种编程语言的代码来完成此操作。