#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», «богатый топор»,…
- Можно ли сначала получить «точные совпадения» с этими функциями utl или есть какая-либо функция, которая лучше соответствует моим требованиям? Наш нечеткий поиск должен быть больше сосредоточен на пропуске некоторых символов, а не на замене их другими.
- Можно ли не учитывать длину слова с помощью этих функций? (например, когда я набираю «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>