Как получить почти совпадающую строку из таблицы Oracle?
У меня есть таблица в Oracle с четырьмя столбцами.
Теперь пользователь может ввести входную строку как "операция по колено вправо" (которая действительна) для моего запроса, и мой запрос должен вернуть код ICD (IKR123), который соответствует большей части слова в столбце DiagnosisName.
Ниже приведен мой текущий запрос (не выдает правильный вывод)
SELECT diagnosisname
FROM
(SELECT diagnosisname,
UTL_MATCH.jaro_winkler_similarity('%operation Knee right%',diagnosisname)
FROM icd_code
ORDER BY UTL_MATCH.EDIT_DISTANCE_SIMILARITY('%operation Knee right%',diagnosisname) DESC
)
WHERE ROWNUM<2;
Этот запрос дает мне вывод "Операция на левом колене", но я ожидаю "Операция на правом колене".
2 ответа
Есть несколько замечаний по поводу использования UTL_MATCH:
- EDIT_DISTANCE_SIMILARITY: возвращает целое число от 0 до 100, где 0 указывает на отсутствие сходства вообще, а 100 указывает на идеальное совпадение.
- JARO_WINKLER_SIMILARITY: Возвращает целое число от 0 до 100, где 0 указывает на отсутствие сходства вообще, а 100 указывает на идеальное совпадение, но пытается учесть возможные ошибки ввода данных.
ORDER BY UTL_MATCH.EDIT_DISTANCE_SIMILARITY ('% операция по колено справа%', имя диагноза) DESC
Это не даст вам правильного результата. Поскольку вы рассматриваете только возможное сходство, но не учитывает ошибки при вводе данных. Итак, вы должны использовать JARO_WINKLER_SIMILARITY.
операция по колено справа
Вы должны иметь в виду случай ввода и значения столбца для сравнения. Они должны быть в аналогичном случае для правильного соответствия. Вы передаете ввод в LOWERCASE, однако значения вашего столбца находятся в INITCAP. Лучше преобразовать значения столбца и входные данные в аналогичный случай.
Давайте посмотрим на демонстрацию ниже, чтобы понять:
SQL> WITH DATA AS(
2 SELECT 'Heart Operation' diagnosis_name, 'IH123' icd_code FROM dual UNION ALL
3 SELECT 'Knee Operation' diagnosis_name, 'IK123' icd_code FROM dual UNION ALL
4 SELECT 'Left Knee Operation' diagnosis_name, 'IKL123' icd_code FROM dual UNION ALL
5 SELECT 'Right Knee Operation' diagnosis_name, 'IKR123' icd_code FROM dual UNION ALL
6 SELECT 'Fever' diagnosis_name, 'IF123' icd_code FROM dual
7 )
8 SELECT t.*,
9 utl_match.edit_distance_similarity(upper(diagnosis_name),upper('operation Knee right')) eds,
10 UTL_MATCH.jaro_winkler_similarity (upper(diagnosis_name),upper('operation Knee right')) jws
11 FROM DATA t
12 ORDER BY jws DESC
13 /
DIAGNOSIS_NAME ICD_CO EDS JWS
-------------------- ------ ---------- ----------
Right Knee Operation IKR123 20 72
Knee Operation IK123 20 70
Heart Operation IH123 25 68
Left Knee Operation IKL123 25 64
Fever IF123 15 47
SQL>
Итак, вы видите, как оба отличаются друг от друга. jaro_winkler_simility лучше справляется с выявлением ошибок при вводе данных и дает наиболее точное совпадение. Исходя из этого, просто выберите первую строку после сортировки по убыванию:
SQL> WITH DATA AS(
2 SELECT 'Heart Operation' diagnosis_name, 'IH123' icd_code FROM dual UNION ALL
3 SELECT 'Knee Operation' diagnosis_name, 'IK123' icd_code FROM dual UNION ALL
4 SELECT 'Left Knee Operation' diagnosis_name, 'IKL123' icd_code FROM dual UNION ALL
5 SELECT 'Right Knee Operation' diagnosis_name, 'IKR123' icd_code FROM dual UNION ALL
6 SELECT 'Fever' diagnosis_name, 'IF123' icd_code FROM dual
7 )
8 SELECT diagnosis_name
9 FROM
10 (SELECT t.*,
11 utl_match.edit_distance_similarity(upper(diagnosis_name),upper('operation Knee right')) eds,
12 UTL_MATCH.jaro_winkler_similarity (upper(diagnosis_name),upper('operation Knee right')) jws
13 FROM DATA t
14 ORDER BY jws DESC
15 )
16 WHERE rownum = 1
17 /
DIAGNOSIS_NAME
--------------------
Right Knee Operation
SQL>
Пожалуйста, попробуйте этот запрос. Это может помочь решить вашу проблему.
SELECT diagnosisname
FROM (SELECT diagnosisname, UTL_MATCH.jaro_winkler_similarity('%operation Knee right%',diagnosisname)
FROM icd_code
WHERE UTL_MATCH.jaro_winkler_similarity('%operation Knee right%',diagnosisname) = 100
ORDER BY UTL_MATCH.EDIT_DISTANCE_SIMILARITY('%operation Knee right%',diagnosisname) DESC)
WHERE ROWNUM<2