Получение похожих строк в 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;
Другие вопросы по тегам