Поиск строк, которые отличаются не более чем одной буквой из заданной строки в 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 для реализации этого алгоритма для вашего конкретного механизма БД.
Ответ 3
То, что вы ищете, это " Приблизительное соответствие строк". Для этого можно использовать " алгоритм вычисления расстояния Левенштейна". Я не уверен, но надеюсь, что этот ответ поможет
Ответ 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