Получение похожих строк в PL/SQL с хорошей производительностью
У меня есть большая таблица в моей базе данных Oracle (12c), и у меня есть много строк, которые нужно сравнивать друг с другом. Я хочу увидеть, какие строки похожи.
Пример:
Привет Мир Бостон в Америке
Привет Мир Берлин в Германии
Должны быть определены как похожие строки, в то время как
Привет Мир Париж во Франции
Привет Детройт хороший город
не должны быть обнаружены как похожие. Как я могу сделать это в Oracle PL/SQL эффективно и точно?
1 ответ
Вы должны использовать Коэффициент Кости, который имеет хороший баланс между производительностью и эффективностью. Это даст вам НОМЕР, который представляет, насколько похожи две строки. Вы можете запустить эту функцию для всех ваших строк, сравнивая их друг с другом, а затем выбрать те, которые имеют большой коэффициент (они будут очень похожи).
-- Dice-Coefficient in Oracle PL/SQL
-- http://en.wikipedia.org/wiki/Dice%27s_coefficient
-- http://en.wikipedia.org/wiki/S%C3%B8rensen_similarity_index
-------------------------------------------------------------------------------
FUNCTION DICE_COEFF(p_str1 IN VARCHAR2, p_str2 IN VARCHAR2) RETURN NUMBER DETERMINISTIC IS
co_substr_len CONSTANT NUMBER := 2;
TYPE ty_varchar_assoc IS TABLE OF VARCHAR2(100) INDEX BY VARCHAR2(100);
v_x ty_varchar_assoc;
v_y ty_varchar_assoc;
v_inter ty_varchar_assoc;
v_part VARCHAR2(10);
BEGIN
-- building set X
FOR i IN 1 .. length(p_str1) - co_substr_len + 1 LOOP
v_part := substr(p_str1, i, co_substr_len);
v_x(v_part) := v_part;
END LOOP;
-- building set Y
FOR i IN 1 .. length(p_str2) - co_substr_len + 1 LOOP
v_part := substr(p_str2, i, co_substr_len);
v_y(v_part) := v_part;
IF v_x.exists(v_part) THEN
v_inter(v_part) := v_part; -- build intersect
END IF;
END LOOP;
RETURN 2 * v_inter.count /(v_x.count + v_y.count);
END DICE_COEFF;