Нечеткий поиск Oracle с функциями UTL

#sql #oracle #fuzzy-search #edit-distance #jaro-winkler

Вопрос:

Мне нужно реализовать нечеткий поиск на уровне базы данных, но у меня возникли некоторые незначительные проблемы. Вот мой SQL-код для демонстрации :

 SELECT *
   FROM (SELECT *
   FROM TOOLS 
   WHERE UTL_MATCH.jaro_winkler_similarity(UPPER('sample tool'), UPPER(NAME)) > 80
   ORDER BY UTL_MATCH.EDIT_DISTANCE_SIMILARITY('sample tool', NAME) DESC)
   where ROWNUM <= 10;
 

Я выбираю 10 инструментов, которые лучше всего соответствуют критериям jaro winkler, и редактирую функции utl сходства расстояний. Борьба, которую я испытываю, заключается в том, что сначала я не получаю точных совпадений. Например, когда я набираю «богатый», лучшим кандидатом является «mich», а затем инструменты с именем «богатый», например «богатый 12», «богатый топор»,…

  1. Можно ли сначала получить «точные совпадения» с этими функциями utl или есть какая-либо функция, которая лучше соответствует моим требованиям? Наш нечеткий поиск должен быть больше сосредоточен на пропуске некоторых символов, а не на замене их другими.
  2. Можно ли не учитывать длину слова с помощью этих функций? (например, когда я набираю «di», я хочу получить результаты как «динозавр», но слово не соответствует моим критериям оценки только потому, что оно длинное, и я не получаю результатов.

Ответ №1:

Сначала оцените результаты, выберите тех, у кого самый высокий ранг. Что-то вроде этого (читайте комментарии в коде):

 SQL> with
  2  tools (name) as
  3    -- sample data
  4    (select 'mich' from dual union all
  5     select 'rich 12' from dual union all
  6     select 'rich ax' from dual
  7    ),
  8  temp as
  9    -- rank similirities first
 10    (select name,
 11         utl_match.jaro_winkler_similarity('amp;amp;par_tool', name) sim,
 12         --
 13         rank() over (order by
 14           utl_match.jaro_winkler_similarity('amp;amp;par_tool', name) desc) rnk
 15     from tools
 16    )
 17  -- finally, return the "top" similar values
 18  select name, sim, rnk
 19  from temp
 20  where rnk = 1;
Enter value for par_tool: rich

NAME              SIM        RNK
---------- ---------- ----------
rich 12            91          1
rich ax            91          1

SQL> undefine par_tool
SQL> /
Enter value for par_tool: mick

NAME              SIM        RNK
---------- ---------- ----------
mich               88          1

SQL>