http://www.artfulsoftware.com/infotree/queries.php?&bw=1280#552

$word = strtolower($_GET['term']); 

$lev = 0;

$q = mysql_query("SELECT `term` FROM `words`"); 
while($r = mysql_fetch_assoc($q)) 
{ 
    $r['term'] = strtolower($r['term']); 

    $lev = levenshtein($word, $r['term']);

    if($lev >= 0 && $lev < 5)
    {
        $word = $r['term'];
    }
}

могу перенести все это в один запрос? Не хочу запрашивать все термины и выполнять фильтрацию в PHP.

Ответы на вопрос(8)

http://www.artfulsoftware.com/infotree/queries.php#552) в ваш запрос.

Вы должны использовать mysqli_query ($ q), потому что mysql_query ($ q) устарела и может быть удалена в будущих версиях php!

$word = mysql_real_escape_string($word);
$query = "SELECT `term` FROM `words` WHERE levenshtein('$word', `term`)   BETWEEN 0 AND 4";
mysqli_qery($query);

реализуя алгоритм в PL / SQL внутри функции, которая может быть вызвана.

 Randy29 мар. 2017 г., 19:19
Сорт-да - вопрос был о том, как структурировать решение «в одном запросе» - я советую переместить усложнение в функцию, чтобы упростить сам запрос.
 Drumbeg30 мар. 2017 г., 11:55
Было бы здорово, если бы вы могли показать нам код.
 Drumbeg29 мар. 2017 г., 09:40
Отлично, так что вы говорите нам, что эта проблема требует некоторого кода!

можете ли вы переместить функциональность levenshtein в mysql, вы не сможете.

Хорошо, вы можете, но это не легче, чем просто сделать это в php.

http://www.artfulsoftware.com/infotree/queries.php?&bw=1280#552

но @profitphp прав, вы не можете сделать это в MySQL без библиотеки levenstein.

$word = strtolower($_GET['term']);

$q = mysql_uqery("SELECT LOWER(`term`) FROM `words`");

while($r = mysql_fetch_assoc($q)) { 

    $lev = levenshtein($word, $r['term']);

    ....

}
Решение Вопроса

Тебе необходимофункция Левенштейна в MySQL и запрос как

$word = mysql_real_escape_string($word);
mysql_qery("SELECT `term` FROM `words` WHERE levenshtein('$word', `term`) BETWEEN 0 AND 4");
 vishal29 авг. 2013 г., 14:13
Это подходит для работы с большими наборами данных? Я пытаюсь запустить LEVENSHTEIN для 458546 записей, запрос не отвечает.
 K.A.F.25 июн. 2013 г., 22:08
Запросы выше не будут выполнены, если вы сначала не измените разделитель SQL. использованиеDELIMITER @ перед запросами добавьте свой новый @ разделитель, после ввода каждого запроса затем измените свой разделитель обратно наDELIMITER ;
 John Weisz11 февр. 2015 г., 10:49
@vishal Нет, по крайней мере, не в его нынешнем виде. Алгоритм Левенштейна имеет сложностьO(n*m), гдеn длина первого слова, иm это второй. Тем не менее, я вижунесколько способы, которыми этоможет быть оптимизировано если вы введетепараметр максимального расстояния, Сначала вы сравниваете две строки, если их разность длин больше, чем параметр max-distance. Если это так, вынемедленно возврат с максимальным значением расстояния. Затем вы проверяете значение текущего расстояния в каждом цикле, и если оно превысило максимум, вы возвращаетесь с этим значением.
 Imabot18 июл. 2018 г., 08:19
У меня та же проблема, что и у Pascal при импорте функции: «# 1064 - у вас ошибка в синтаксисе SQL; проверьте руководство, соответствующее версии вашего сервера MySQL, на предмет правильного синтаксиса, который можно использовать рядом со строкой 5». , Я не могу найти проблему, кто-то может помочь?
 Pascal Klein12 дек. 2014 г., 17:43
Я получаю сообщение об ошибке при попытке создать функцию: # 1064 - у вас есть ошибка в синтаксисе SQL; проверьте руководство, соответствующее вашей версии сервера MySQL, чтобы найти правильный синтаксис для использования рядом с '' в строке 5. Может кто-нибудь передать полностью рабочий код?

вы можете сначала отфильтровать слова, используя SOUNDEX:

$word = strtolower(mysql_real_escape_string($_GET['term']));

$rs = mysql_query("SELECT LOWER(`term`) FROM `words` WHERE SOUNDEX(term) = SOUNDEX(" . $word . ")");

while ($row = mysql_fetch_assoc($rs)) { 

    $lev = levenshtein($word, $row['term']);

    ....

}

Если у вас есть достаточно времени, чтобы поиграть с расширением или процедурой C, вы можете добиться лучшей производительности, но фильтрация записей в 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 и импортируйте его в свою базу данных следующим образом:

source /tmp/mysql_udf.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;

Кроме того, помните, что значение «порога» должно меняться относительно длины исходного слова. Лучше думать об этом с точки зрения процентного значения, то есть половина вашего слова = 50%, половина термина = 2.

 Gordon Freeman04 янв. 2018 г., 12:11
Отредактировано, чтобы заменить ссылку соответствующим содержанием. Лучше? :)
 bwright03 янв. 2018 г., 09:25
Первая ссылка выше (kristiannissen.wordpress.com/2010/07/08/mysql-levenshtein) больше не активен.

я обнаружил, что обрабатывать операции Левенштейна и сортировку в PHP гораздо эффективнее, чем в MySQL. например запрос около 1000 записей:

MySQL (~ 0,0050 с) -> PHP Левенштейн (~ 1,300 с)

против

MySQL Левенштейн (> = 5000 с) -> PHP (~ 0,250 с)

Есть также много других вариантов оптимизации поисковых систем, но если вы хотите использовать Levenshtein, просто помните о данных, которые вы будете обрабатывать, и о задержках, которые вы хотите.

Ваш ответ на вопрос