Поиск строк, которые отличаются не более чем одной буквой из заданной строки в SAS с помощью PROC SQL

Сначала рассмотрим какой-то контекст. Я использую proc sql в SAS и вам нужно получить все записи в наборе данных (с несколькими миллионами записей), которые имеют переменную "Имя", равную (скажем) "Массачусетс". Разумеется, поскольку данные были введены человеком вручную, рядом со всеми возможными ошибками орфографии ( "Amssachusetts", "Kassachusetts" и т.д.).

Я обнаружил, что несколько записей попадают более чем на два символа, поэтому код

Name like "__ssachusetts" OR Name like "_a_sachusetts" OR ... OR Name like "Massachuset__"

будет выбирать записи, которые я ищу. Тем не менее, я надеюсь, что должен быть более удобный способ писать

Name that differs by at most 2 characters from "Massachusetts";

Есть ли? Или есть другая стратегия для получения этих записей? Я пробовал искать как stackoverflow, так и в Интернете, но был неудачным. Я также относительный новичок как с SQL, так и с SAS.

Дополнительная информация: База данных не находится на английском языке (и фактическая строка не является "Массачусетс" ), поэтому использование SOUNDEX на самом деле невозможно (если это когда-либо было).

Спасибо заранее.

(Изменить: улучшено название)

Ответы

Ответ 1

SAS имеет встроенные функции COMPGED и COMPLEV для вычисления расстояний между строками. Вот пример, который показывает, как выбрать только те, у которых расстояние редактирования Levenshtein меньше или равно 2.

data typo;
input name $20.;
datalines;
massachusetts
masachusets
mssachusetts
nassachusets
nassachussets
massachusett
;

proc sql;
  select name from typo
  where complev(name, "massachusetts") <= 2;
quit;

Ответ 2

Существуют и другие фонетические алгоритмы, такие как расстояние Хэмминга, которое должно работать лучше. Вы можете искать в google для реализации этого алгоритма для вашего конкретного механизма БД.

Ответ 4

Вы можете реализовать хранимую функцию этого типа (синтаксис Oracle, преобразовать в вашу СУБД):

CREATE FUNCTION distance(one VARCHAR2, two VARCHAR2) RETURN NUMBER IS
DETERMINISTIC
BEGIN
  -- do some comparison here
END distance;

И затем используйте его в SQL:

SELECT * FROM table WHERE distance(name, 'Massachusetts') <= 2

Конечно, эти вещи, как правило, довольно медленные...

Ответ 5

Я знаю, что это слишком поздно, но так как это может также дать идеи тем, кто ищет эту тему: То, что вы рассматриваете, представляет собой семантический многоуровневый дизайн, вам нужно будет реализовать некоторую условную логику для этих разных текстовых сравнений, используя расстояния Lenvenschtien, такие как Jaro-Winkler, для сравнения текста разной длины и Хэмминга для тех же длин, которые вы предполагаете простое транс-позиционирование текста. Это ничего нового в наши дни со всеми различными программами интеллектуального анализа текста. Вот сообщение, которое очень хорошо на мой взгляд; Функция сравнения строк Jaro-Winkler в SAS