Можно ли использовать soundex для части столбца в MySQL?

Можно ли использовать soundex для сравнения части столбца с поисковым термином? Например, если пользователь ищет "пятьдесят три" - он найдет "Nirve Sports Fifty-Three Cruiser in Gold Metallic". Я попытался объединить soundex с функцией locate, но получил ошибку. Вот мой PHP-код:

$soundex = soundex($keyword);
$soundexPrefix = substr($soundex, 0, 2); 
$sql = "SELECT name ".
"FROM products WHERE SOUNDEX(LOCATE('$keyword', name)) LIKE '%$soundexPrefix%'";

2 ответа

Решение

Вам нужно разбить каждое слово и сделать SOUNDEX Сравнение, о котором я собираюсь рассказать вам в этой функции.

Используя функцию

Пример использования: SELECT p.name FROM products p WHERE soundex_match('fiftythree', p.name, ' ')

Требуется 3 аргумента:

  • игла: слово, которое вы ищете
  • стог сена: строка слов, среди которых вы ищете
  • splitChar: символ пробела, который разделит строку на отдельные слова. Обычно это пробел ('')

Если какое-либо слово в стоге сена звучит похоже на иглу, в противном случае функция вернет 1 и 0.

Создание функции в вашей базе данных

Поэтому зайдите в свою базу данных (phpMyAdmin или командную строку) и выполните это, вам нужно сделать это только один раз):

drop function if exists soundex_match;
delimiter $$
create function soundex_match (needle varchar(128), haystack text, splitChar varchar(1)) returns tinyint
  deterministic
  begin
    declare spacePos int;
    declare searchLen int default length(haystack);
    declare curWord varchar(128) default '';
    declare tempStr text default haystack;
    declare tmp text default '';
    declare soundx1 varchar(64) default soundex(needle);
    declare soundx2 varchar(64) default '';

    set spacePos = locate(splitChar, tempStr);

    while searchLen > 0 do
      if spacePos = 0 then
        set tmp = tempStr;
        select soundex(tmp) into soundx2;
        if soundx1 = soundx2 then
          return 1;
        else
          return 0;
        end if;
      end if;

      if spacePos != 0 then
        set tmp = substr(tempStr, 1, spacePos-1);
        set soundx2 = soundex(tmp);
        if soundx1 = soundx2 then
          return 1;
        end if;
        set tempStr = substr(tempStr, spacePos+1);
        set searchLen = length(tempStr);
      end if;

      set spacePos = locate(splitChar, tempStr);

    end while;

    return 0;

  end
$$
delimiter ;

http://www.imranulhoque.com/mysql/mysql-function-soundex-match-multi-word-string/

Возвращаясь к этому вопросу; Я обновил решение @msigman для размещения строк разной длины (т. е. «Джеймс» похож на «Джеймстаун»)...

      DROP FUNCTION IF EXISTS senf_soundex;
DELIMITER $$
CREATE FUNCTION senf_soundex (_needle VARCHAR(128), _haystack TEXT, _delimiter VARCHAR(1)) 
    RETURNS TINYINT
    DETERMINISTIC
    BEGIN

        DECLARE int_index   INT;
        DECLARE int_length  INT             DEFAULT LENGTH(_haystack);
        DECLARE int_result  TINYINT         DEFAULT 0;
        DECLARE str_remnant TEXT            DEFAULT _haystack;
        DECLARE snd_needle  VARCHAR(64)     DEFAULT TRIM(TRAILING '0' FROM LEFT(SOUNDEX(_needle), 4));
                        
        SET int_index = LOCATE(_delimiter, str_remnant);
    
        WHILE int_length > 0 DO
            IF int_index = 0 THEN
                SET int_result = IF(snd_needle = LEFT(SOUNDEX(str_remnant), LEAST(4, LENGTH(snd_needle))),1,0);
                RETURN int_result;
            ELSE
                IF snd_needle = LEFT(SOUNDEX(SUBSTR(str_remnant, 1, int_index-1)), LEAST(4, LENGTH(snd_needle))) THEN
                    RETURN 1;
                END IF;
                SET str_remnant = SUBSTR(str_remnant, int_index+1);
                SET int_length = LENGTH(str_remnant);
            END IF;
        
            SET int_index = LOCATE(_delimiter, str_remnant);
        
        END WHILE;
    
        RETURN 0;
    
    END
$$ DELIMITER ;
Другие вопросы по тегам