Находить одну запись пользователя в некоторых неполных данных?

Я нахожусь в процессе создания системы, в которой пользователи должны зарегистрироваться. Эти пользователи, вероятно, также будут частью более крупной базы данных клиентов, и я хотел бы связать регистрацию с идентификатором пользователя в более крупной базе данных клиентов.

База данных клиентов несколько неполная. У некоторых клиентов просто есть телефонный номер, и он может иметь пробелы в разных местах в зависимости от того, кто / что ввел его. У других клиентов есть только адрес электронной почты, и он может содержать опечатки из-за того, что он был написан от руки, а затем обработан кем-то еще позже. Совсем кошмар на самом деле.

Я хотел бы найти ближайшую запись к тому, что пользователь ввел в систему, которую я строю. Эти данные довольно просты и будут проверены. Эти данные:

  • Имя
  • Фамилия
  • ДОБ (ГГГГ-ММ-ДД)
  • Адрес электронной почты
  • Номер телефона

Моя первоначальная мысль — использовать алгоритм расстояния Левенштейна для вычисления «расстояния строки» для каждого из полей, если они не пусты, а затем упорядочить по общему количеству баллов. В приведенном ниже коде не показано, чтобы все было хорошо и читабельно, но я, очевидно, также обрежу (возможно, даже просто уберу) весь пробел.

Как псевдокод:

SELECT c.customerID
FROM   customers c
WHERE  ( c.first_name IS NULL OR ( Levenshtein(c.first_name, $first_name) < 3 ) )
AND    ( c.last_name IS NULL OR ( Levenshtein(c.last_name, $last_name) < 3 ) )
AND    ( c.email IS NULL OR ( Levenshtein(c.email, $email) < 3 ) )
AND    ( c.telephone IS NULL OR ( Levenshtein(c.telephone, $telephone) < 3 ) )

Просто к сведению, я использую PHP (Laravel) и MySQL для обеих баз данных.

Я здесь на правильном пути или мне следует использовать что-то кроме Левенштейна? Стоит ли сравнивать какую-то комбинацию баллов по всем полям?

1

Решение

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

Подготовка данных

Прежде всего, для соответствия я рекомендую преобразовать данные, чтобы устранить, возможно, весь шум, например. конвертировать строки в верхний регистр, удалять пробелы, удалять все нецифровые цифры из телефонных номеров и т. д.

Нахождение ближайшего совпадения в неполных данных

Во-вторых, установка произвольных порогов (например, «меньше 3» выше) делает его немного жестким. Несмотря на большую нагрузку на процессор, вам может быть лучше отсортировать результаты по «разности факторов»:

SELECT c.customerID
FROM   customers c
ORDER BY
Levenshtein(c.first_name, $first_name)) +
Levenshtein(c.last_name, $last_name) +
Levenshtein(c.email, $email) +
Levenshtein(c.telephone, $telephone) asc
LIMIT 0,1;

Очевидно, вы можете добавить некоторую безопасность, чтобы не совпадать, когда различия смехотворно велики, но вы поняли идею. В тех случаях, когда оба объекта не имеют данных в одном и том же поле (например, оба пропускают электронную почту), подход все еще в порядке. Проблемы возникают, когда отсутствует только одна сторона — тогда мы получим большой удар за разницу. Мы можем усложнить запрос, чтобы избежать его:

ORDER BY
(if(c.first_name is null OR c.first_name = '' OR $first_name = '', 0, Levenshtein(c.first_name, $first_name))) +
...

Для краткости укорочен до одной строки — мы вычисляем Lev dist, только если есть данные для сравнения.

Упущения

Для всех записей с коэффициентом разности, превышающим X, вы можете подумать о каком-то флаге, позволяющем людям решать. Я уверен, что после некоторого времени, проведенного в обзоре, вы придумаете больше правил для его автоматизации.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]