Вот как это может быть сделано с помощью Левенштейна:
Создать эту функцию: (Execute это первый)
CREATE FUNCTION ufn_levenshtein(@s1 nvarchar(3999), @s2 nvarchar(3999))
RETURNS int
AS
BEGIN
DECLARE @s1_len int, @s2_len int
DECLARE @i int, @j int, @s1_char nchar, @c int, @c_temp int
DECLARE @cv0 varbinary(8000), @cv1 varbinary(8000)
SELECT
@s1_len = LEN(@s1),
@s2_len = LEN(@s2),
@cv1 = 0x0000,
@j = 1, @i = 1, @c = 0
WHILE @j <= @s2_len
SELECT @cv1 = @cv1 + CAST(@j AS binary(2)), @j = @j + 1
WHILE @i <= @s1_len
BEGIN
SELECT
@s1_char = SUBSTRING(@s1, @i, 1),
@c = @i,
@cv0 = CAST(@i AS binary(2)),
@j = 1
WHILE @j <= @s2_len
BEGIN
SET @c = @c + 1
SET @c_temp = CAST(SUBSTRING(@cv1, @[email protected], 2) AS int) +
CASE WHEN @s1_char = SUBSTRING(@s2, @j, 1) THEN 0 ELSE 1 END
IF @c > @c_temp SET @c = @c_temp
SET @c_temp = CAST(SUBSTRING(@cv1, @[email protected]+1, 2) AS int)+1
IF @c > @c_temp SET @c = @c_temp
SELECT @cv0 = @cv0 + CAST(@c AS binary(2)), @j = @j + 1
END
SELECT @cv1 = @cv0, @i = @i + 1
END
RETURN @c
END
(Функция развившейся Джозефом Гама)
, а затем просто использовать этот запрос, чтобы получить совпадения
SELECT A.Customer,
b.ID,
b.Customer
FROM #POTENTIALCUSTOMERS a
LEFT JOIN #ExistingCustomers b ON dbo.ufn_levenshtein(REPLACE(A.Customer, ' ', ''), REPLACE(B.Customer, ' ', '')) < 5;
Полный Script af тер вы создаете функцию:
IF OBJECT_ID('tempdb..#ExistingCustomers') IS NOT NULL
DROP TABLE #ExistingCustomers;
CREATE TABLE #ExistingCustomers
(Customer VARCHAR(255),
ID INT
);
INSERT INTO #ExistingCustomers
VALUES
('Ed''s Barbershop',
1002
);
INSERT INTO #ExistingCustomers
VALUES
('GroceryTown',
1003
);
INSERT INTO #ExistingCustomers
VALUES
('Candy Place',
1004
);
INSERT INTO #ExistingCustomers
VALUES
('Handy Man',
1005
);
IF OBJECT_ID('tempdb..#POTENTIALCUSTOMERS') IS NOT NULL
DROP TABLE #POTENTIALCUSTOMERS;
CREATE TABLE #POTENTIALCUSTOMERS(Customer VARCHAR(255));
INSERT INTO #POTENTIALCUSTOMERS
VALUES('Eds Barbershop');
INSERT INTO #POTENTIALCUSTOMERS
VALUES('Grocery Town');
INSERT INTO #POTENTIALCUSTOMERS
VALUES('Candy Place');
INSERT INTO #POTENTIALCUSTOMERS
VALUES('Handee Man');
INSERT INTO #POTENTIALCUSTOMERS
VALUES('Beauty Salon');
INSERT INTO #POTENTIALCUSTOMERS
VALUES('The Apple Farm');
INSERT INTO #POTENTIALCUSTOMERS
VALUES('Igloo Ice Cream');
INSERT INTO #POTENTIALCUSTOMERS
VALUES('Ride-a-Long Bikes');
SELECT A.Customer,
b.ID,
b.Customer
FROM #POTENTIALCUSTOMERS a
LEFT JOIN #ExistingCustomers b ON dbo.ufn_levenshtein(REPLACE(A.Customer, ' ', ''), REPLACE(B.Customer, ' ', '')) < 5;
Здесь вы можете найти T-SQL пример в http://www.kodyaz.com/articles/fuzzy-string-matching-using-levenshtein-distance-sql-server.aspx
Ближе всего я дошел до сих пор, но все же некоторые проблемы. Во-первых, для выполнения запроса требуется очень много времени. Во-вторых, я получаю большое количество ложноположительных матчей. Например, один из моих потенциальных клиентов соответствует 700 существующим клиентам ... Есть ли способ получить расстояние levenshtein как столбец в инструкции select? – hansolo
использование этого: SELECT A.Customer, b.ID, b.Customer, \t dbo.ufn_levenshtein (REPLACE (A.Customer, '', ''), REPLACE (B.Customer, '', '')) FROM #POTENTIALCUSTOMERS a LEFT JOIN #ExistingCustomers b ON dbo.ufn_levenshtein (REPLACE (A.Customer, '', ''), REPLACE (B.Customer, '', '')) <5; –
вам нужно играть с дистанцией и посмотреть, какие сюиты вам лучше всего ... прямо сейчас его соответствие «<5». Как и предлагалось iamdave, производительность всегда будет проблемой с такими типами совпадений –