Die Levenshtein-Distanz berechnet die Anzahl an Zeichen die nötig sind, um 2 Wörter durch Ergänzen oder Löschen aneinander anzugleichen (identisch machen).
Die aus PHP bekannte Funktion levenshtein() ist in MySQL nicht implementiert. Es gibt aber Möglichkeiten sie nachträglich zu integrieren. Entweder durch die in C geschrieben UDF Plugins oder eben durch direkte Eingabe von SQL Anweisungen. Letztere, die Stored Procedures haben den Vorteil, dass sie ohne Zugang zum Server bei entsprechender Berechtigung z.B. über phpMyAdmin installiert werden können. Nachteilig ist unter anderem die schlechte Geschwindigkeit.
Ich zeige hier die SQL Anweisung und muss leider ernüchternd sagen, dass die Geschwindigkeit echt miserable ist. Also dient die Funktion lediglich zu Testzewcken.
Der Aufruf:
SELECT `column`, LEVENSHTEIN('baum', `column`) AS `dist`
FROM `table`
HAVING `dist` BETWEEN 1 AND
ORDER BY `dist` ASC
LIMIT 10;
Funktion:
Die LEVENSHTEIN-Funktion liefert einen Integer Wert zurück, der bei identischen Wörtern 0 ist. Wenn sehr ähnliche Wörter gefunden werden sollen, sollte die Distanz zwischen 1 und 5 liegen. Im Beispiel werden als ähnlich Wörter zu 'baum' gesucht.
Der Funktionscode: Quelle: http://kristiannissen.wordpress.com/2010/07/08/mysql-levenshtein/
Der erste Befehl kann natürlich weg gelassen werden und dient nur zum Testen. Er entfernt zuvor schon deklarierte Funktionen.
DROP FUNCTION IF EXISTS levenshtein;
delimiter // 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; 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 // delimiter ;
