Существует два способа реализации функции Левенштейна в MySQL.Первый заключается в создании хранимой функции, которая во многом похожа на хранимую транзакцию, за исключением того, что она имеет различные входные и выходные данные.Это хорошо для небольших наборов данных, но немного медленно для всего, что приближается к нескольким тысячам строк.
CREATE FUNCTION levenshtein( s1 VARCHAR(255), s2 VARCHAR(255) )
RETURNS INT
DETERMINISTIC
BEGIN
DECLARE s1_len, s2_len, i, j, c, c_temp, cost INT;
DECLARE s1_char CHAR;
-- max strlen=255
DECLARE cv0, cv1 VARBINARY(256);
SET s1_len = CHAR_LENGTH(s1), s2_len = CHAR_LENGTH(s2), cv1 = 0x00, j = 1, i = 1, c = 0;
IF s1 = s2 THEN
RETURN 0;
ELSEIF s1_len = 0 THEN
RETURN s2_len;
ELSEIF s2_len = 0 THEN
RETURN s1_len;
ELSE
WHILE j <= s2_len DO
SET cv1 = CONCAT(cv1, UNHEX(HEX(j))), j = j + 1;
END WHILE;
WHILE i <= s1_len DO
SET s1_char = SUBSTRING(s1, i, 1), c = i, cv0 = UNHEX(HEX(i)), j = 1;
WHILE j <= s2_len DO
SET c = c + 1;
IF s1_char = SUBSTRING(s2, j, 1) THEN
SET cost = 0; ELSE SET cost = 1;
END IF;
SET c_temp = CONV(HEX(SUBSTRING(cv1, j, 1)), 16, 10) + cost;
IF c > c_temp THEN SET c = c_temp; END IF;
SET c_temp = CONV(HEX(SUBSTRING(cv1, j+1, 1)), 16, 10) + 1;
IF c > c_temp THEN
SET c = c_temp;
END IF;
SET cv0 = CONCAT(cv0, UNHEX(HEX(c))), j = j + 1;
END WHILE;
SET cv1 = cv0, i = i + 1;
END WHILE;
END IF;
RETURN c;
END//
Сохраните вышеуказанный код в файле .sql и импортируйте его в свою базу данных следующим образом:*
Второй метод - реализовать пользовательскую функцию на C / C ++ и связать ее с MySQL в виде общей библиотеки (файл * .so).Этот метод также использует STORED FUNCTION для вызова библиотеки, что означает, что фактический запрос для этого или первого метода может быть идентичным (при условии, что входные данные для обеих функций одинаковы).Вы можете узнать больше об этом методе здесь: http://samjlevy.com/mysql-levenshtein-and-damerau-levenshtein-udfs/
При любом из этих методов ваш запрос будет выглядеть примерно так:
SELECT term FROM words WHERE levenshtein(term, 'term') < 5;
Кроме того, помните, что значение 'threshold'должен измениться относительно оригинальной длины слова.Лучше думать об этом в терминах процентного значения, то есть половина вашего слова = 50%, половина термина = 2.