1

Является ли функция Levenshtein правильной/лучшей функцией, чтобы найти наивысшее соответствие между двумя строками?Получить наивысшее соответствие между двумя строками

например:

string1 = CCC14E0APJ 
string2 = CCC14E0APJ123 

Мой конечный результат должен сказать, что CCC14E0APJ является ведущим продуктом CCC14E0APJ123. Я не могу сделать точный матч, потому что некоторые продукты будут выглядеть так.

CCC14E0AP 
CCC14E0APJ 
CCC14E0APK 

которые все совершенно разные продукты. Мастер всегда соответствует 100% -ной строке для самой длинной найденной строки. Для продукта abcde123, если в моей главной таблице есть abcde, то это мастер. Если есть только abc, то это мастер.

+1

ли префиксы строк всегда совпадают, или это может меняться, а? –

+0

всегда согласен, должно быть точное совпадение по всем символам и их порядок – jrdev22

+0

Почему CCC14E0APJ123 выше CCC14E0AP, CCC14E0APK? – Matt

ответ

4

Вы не нуждаетесь в фантазии How-close-is-the-string -функции, а скорее сравнивают начало строки со всеми другими строками, если они начинаются с одной и той же строки. Если это так, тем короче родитель из более ...

С помощью следующего запроса вы получите ParentID, даже в иерархической системе:

DECLARE @dummy TABLE(YourID VARCHAR(100),ParentID VARCHAR(100)); 

INSERT INTO @dummy(YourID) VALUES 
('CCC14E0AP') 
,('CCC14E0APJ') 
,('CCC14E0APK') 
,('CCC14E0APK_1') 
,('CCC14E'); 

WITH DependingIDs AS 
(
    SELECT d.ParentID 
      ,d.YourID 
      ,d2.YourID AS dependingID 
      ,RANK() OVER(PARTITION BY d.YourID ORDER BY LEN(d2.YourID) DESC) AS NextLenght 
    FROM @dummy AS d 
    INNER JOIN @dummy AS d2 ON d.YourID LIKE d2.YourID + '%' AND d.YourID<>d2.YourID 
) 
UPDATE DependingIDs SET ParentID=dependingID 
WHERE NextLenght=1; 

SELECT * FROM @dummy 

Это результат

YourID  ParentID 
CCC14E0AP CCC14E 
CCC14E0APJ CCC14E0AP 
CCC14E0APK CCC14E0AP 
CCC14E0APK_1 CCC14E0APK 
CCC14E  NULL 
3

Для каждой строки вы просто обнаружить максимальную подстроку с помощью APPLY оператора:

DECLARE @t TABLE (p VARCHAR(MAX)); 

INSERT INTO @t 
VALUES ('A'), 
     ('AAAA'), 
     ('AA'), 
     ('BBB'), 
     ('BBBB'), 
     ('BBBBB'), 
     ('BBBBB'), 
     ('C') 

SELECT * 
FROM @t t 
     OUTER APPLY (SELECT TOP 1 p 
         FROM  @t 
         WHERE  t.p <> p AND t.p LIKE p + '%' 
         ORDER BY LEN(p) DESC 
        ) ca 

Выход:

A  NULL 
AAAA AA 
AA  A 
BBB  NULL 
BBBB BBB 
BBBBB BBBB 
BBBBB BBBB 
C  NULL 
+0

Ваше решение сработало, но решение Shnugo было первым и также работало, и я не могу рассказать о плюсах и минусах обоих решений. – jrdev22

+1

@ jrdev22 В этом случае вы можете проголосовать за ответ, нажав на треугольник. Голосование и принятие - это два отдельных шага на SO. Поскольку вы сами пересекли границу с 15 пунктами, вас попросят проголосовать за любой вклад, который вам нравится или не нравится. Это способ сказать * Спасибо * на SO ... Счастливое кодирование! (кстати: +1 с моей стороны) – Shnugo

Смежные вопросы