如何检查一个列值是否包含在另一列值中(TSQL)?

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

我有 2 个包含许多列的表,我想找到 table1.somecolumn 中的值包含在 table2.someothercolumn 中的那些行。示例:

表 1.somecolumn 有 Smith、Peter
table2.someothercolumn 有 peter.smith

那应该是匹配的,我该如何进行这样的搜索?

t-sql substring
3个回答
2
投票

您可以尝试使用

SOUNDEX
DIFFERENCE
函数来帮助匹配字符串文字。

示例:

select difference('peter.green', 'Green, Peter')

返回

2
,其中:

返回的整数是个数 SOUNDEX 值中的字符 是相同的。返回值范围 从 0 到 4:0 表示弱或 没有相似性,4表示强 相似或相同的值。

请参阅 MSDN 上的 SOUNDEXDIFFERENCE 主题。

更新:

当考虑单词顺序时,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

它并不完美,但这是一个很好的起点,可以对其进行调整以提供更高的成功概率。


1
投票

有多种可能的解决方案,具体取决于您的需求: 使用可以创建辅助表来存储每条记录的关键字

  1. 使用辅助表来存储每条记录或记录和字段的关键字。例如。 table_helper(id int Primary key, record_id int, keywords varchar), record_id - 链接到源表。在table1、table2的触发器中填写此表。查找公共行的查询是 table_helper 与其自身的简单交集。您可以为 table1 和 table2 创建一个助手或使用单独的表。
  2. 使用全文索引。

0
投票

如果它遵循严格的模式,以便名称之间始终有逗号和空格,您还可以按逗号和空格分割字符串,请参阅STRING_SPLIT (Transact-SQL)

“史密斯,彼得”上的

string_split()
ID
列将变为:

ID String
1  Smith
1  
1  Peter

然后使用

select somestring like '%'+someotherstring+'%'
(以及
lower
所有字符串)检查一个
String
的所有
ID
: 是否可以在另一表的列中的某处找到。

我不会花时间进一步检查这一点,但您可以逐步到达那里。我认为这不是一个有用的答案,因为您应该使用 SSIS 中的模糊逻辑或 SSIS 的其他(外部)组件等工具来检查模糊名称。还要搜索存储过程。并检查是否可以使用另一种编程语言的代码来完成此操作。

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