我想知道这里是否有人可以为我提出一些解决方案,将两个字符串并逐个单词比较然后给我整个字符串的百分比匹配。
示例:如果我想比较这两个字符串
- 书架上的精灵:圣诞音乐剧(巡回演出)
- 书架上的精灵音乐剧巴尔的摩
在SQL中,如果我做like
比较,它将不匹配。但是如果我可以把每个单词分开看它是否匹配我们会看到7个单词中的6个从字符串2匹配到字符串1。然后输入85% match
谢谢!
需要计算两个字符串之间的相似度。有很多算法可以用来完成这个任务。我们来试试Levenshtein距离和最长公共子序列;各有各的优点。
-- Sample strings
DECLARE
@string1 VARCHAR(100) = 'The Elf on the Shelf: A Christmas Musical (Touring)',
@string2 VARCHAR(100) = 'The Elf on the Shelf Musical Baltimore';
--uncomment to test:
--SELECT @string1 = 'Their', @string2 = 'Theirs'
-- Longest Common Subsequence Solution
SELECT Similarity = 1.*LEN(dbo.LongestCommonSubsequence(@string1,@string2))/L2
FROM
(
SELECT MIN(f.S), MAX(f.S)
FROM (VALUES(LEN(@string1)),(LEN(@string2))) AS f(S)
) f(L1,L2);
-- Levenshtein
SELECT Similarity = (1.*L1-Lev)/L2
FROM
(
SELECT MIN(f.S), MAX(f.S), dbo.LEVENSHTEIN(@string1,@string2)
FROM (VALUES(LEN(@string1)),(LEN(@string2))) AS f(S)
) f(L1,L2,Lev);
每个返回:
Similarity
---------------------------------------
0.62745098039
Similarity
---------------------------------------
0.31372549019
为"their"one_answers";theirs"你得到:
Similarity
---------------------------------------
0.83333333333
Similarity
---------------------------------------
0.66666666666
这是获取匹配单词百分比的一种可能的解决方案,它假设两个字符串之间的单词匹配,而不考虑位置。
我明白它可能不是你真正想要的,也没有做"相似"的事情。话说,但是希望遇见一个百分比的标准匹配。如果不完全是需要的,还有很多余地可以调整。
在这里,两个字符串被分割成行并合并到一个表中,去掉常见的标点符号。然后,row_number窗口函数通过匹配单词对它们进行划分,并对每对进行计数。最后,只对匹配的对进行计数,并对两者中常见的重复单词计数求和,然后作为较短字符串的百分比。
declare
@s1 varchar(100)='The Elf on the Shelf: A Christmas Musical. (Touring)',
@s2 varchar(100)='The Elf on the Shelf Musical, Baltimore';
with words as (
select 1 s, Replace(Replace(Replace(Replace(Replace(value,':',''),',',''),'(',''),')',''),'.','') word
from String_Split(@s1,' ')
union all
select 2, Replace(Replace(Replace(Replace(Replace(value,':',''),',',''),'(',''),')',''),'.','')
from String_Split(@s2,' ')
), matching as (
select *, Row_Number() over(partition by word order by s) rn
from words
), final as (
select * , Count(*) over(partition by word, s) repeating, Count(*) over() * 1.0 totwords, sum(Iif(s=1,1,0)) over() s1words
from matching
outer apply(values(Iif(rn=2 and rn=s,1,0)))x(p)
)
select (Sum (p) + max(case when s=1 and repeating>1 then repeating end))
/ Max(Iif(totwords/s1words>0.5, totwords-s1words, s1words)) * 100 [Matching Words %]
from final
在这里,每个字符串中有6个单词匹配,因此结果是所需的6是较短的7个单词字符串的85.7%。
,DB<例子的在小提琴