Сложный запрос справки для частичного / совпадения по адресу / почтовому индексу и телефону - PullRequest
1 голос
/ 21 января 2011

Пример данных:

$address_1  = '123 Main St.';
$address_2  = 'Suite 200';
$phone      = '1235551212';
$zip        = '12345';

Пример базы данных:

record_id, address_1, address_2, zip, phone
123, '123 main street', '', '12345', '1234567890'
124, '500 E. Ninja Road', 'Suite #200', '12345-1111', '(321)654-0987'
125, '222 where 4 east circle', 'P.O. Box 3', '11111', '1-123-555-1212'

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

Таким образом, $address_1 будет частично соответствовать record_id 123 как '123 Main St.'это вариация «123 главной улицы»$address_2 будет соответствовать record_id 124, поскольку «Люкс 200» является вариацией «Люкс # 200».$phone будет соответствовать record_id 125, поскольку '1235551212' является вариацией '1-123-555-1212'$zip будет соответствовать record_id 123 & 124, поскольку «12345» является вариацией «12345-1111» и соответствует «12345»

ПРИМЕЧАНИЕ. Также можно переключать значения, что означает, что $address_1 может быть отформатирован так: '123 main street' и record_id 123 могут быть такими: '123 Main St.'(Это относится ко всем полям)

Мне предложили попробовать ILIKE, LIKE, SIMILAR , CITEXT и FTS (поиск в свободном тексте) все это здорово, но я не уверен, как реализовать их, чтобы получить желаемые результаты.Я не против запустить несколько запросов для каждого, например, запрос для $address_1 match и другой для $address_2 match и так далее.Я также знаю, что будут ложные срабатывания, а также ложные отрицания, но я надеюсь, что точность составляет около 75% (или лучше).

Один ВАЖНО примечание - это то, что PostgresНа сервере запущена версия 7.4 , и нет планов по обновлению.

Также для большей сложности запроса существует несколько address_1, address_2, zip и * 1042.* (Вспомните отдельный адрес / телефон для дома и офиса)

Вот мои первые попытки решить эту проблему:

У меня была идея создать наиболее распространенные форматы и затем передать их в качестве параметров в запросе.

Что-то вроде:

$address_1  = array(
   '123 Main St.', // original
   '123 main st.', // lower case
   '123 Main St.', // First Letter Upper Case
   '123 MAIN ST.', // ALL Upper Case
   '123 Main St',  // remove punctuation original
   '123 main st',  // remove punctuation lower case
   '123 Main St',  // remove punctuation First Letter Upper Case
   '123 MAIN ST',  // remove punctuation ALL Upper Case  
   '123 Main',     // remove last word original
   '123 main',     // remove last word lower case
   '123 Main',     // remove last word First Letter Upper Case
   '123 MAIN',     // remove last word ALL Upper Case 
   '123 Main%',    // remove last word original with wildcard
   '123 main%',    // remove last word lower case with wildcard
   '123 Main%',    // remove last word First Letter Upper Case with wildcard
   '123 MAIN%'     // remove last word ALL Upper Case with wildcard
);

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

SELECT * 
FROM tbl_name
WHERE address_1 IN (
   '123 Main St.', '123 main st.', '123 Main St.',
   '123 MAIN ST.', '123 Main St', '123 main st',
   '123 Main St', '123 MAIN ST', '123 Main',
   '123 main', '123 Main' '123 MAIN',
   '123 Main%', '123 main%', '123 Main%', 
   '123 MAIN%'
)

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

ОБНОВЛЕНИЕ:

Ну, это вроде работает (отStack Question # 2)

SELECT * 
FROM tbl_name
WHERE LOWER(address_1) ILIKE LOWER('123 Main%')

С использованием метода UNION (из стекового вопроса # 1) для каждого дополнительного поля поиска ищите, как Office и Home

Ответы [ 2 ]

2 голосов
/ 21 января 2011

Если я вас правильно понимаю, вам нужны фрагментарные совпадения от поля к полю (например, «123» соответствует «123-111» и «12345», но не «122234» или «122-345»), и вам нужно избегать всехсимволы при сопоставлении. Это правильно?

Ниже приведен psuedocode, который я бы попробовал сначала:

  • Обработка всех полей ввода для удаления символовопределение фрагментов для сопоставления
  • Выполнение сопоставления фрагментов со значениями данных

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

SELECT * FROM [TABLE_NAME] WHERE address_1 ILIKE '%fragment%'

Вам придется выполнять этот запрос несколько раз, что может быть головной болью производительности, но я считаю, что это может дать вам то, что вы хотите.

1 голос
/ 12 мая 2011

У меня есть несколько предложений по подходам.

Я бы настоятельно рекомендовал убрать все нечисловые числа с номера телефона.Вы можете сделать это в postgres с помощью чего-то вроде

SELECT id FROM [table] WHERE regexp_replace(phone, '[^0-9]', '', 'g') = [$phone];

. Я не уверен, что это сработает для вас, но многие системы проверки адресов игнорируют все, кроме цифр, для сопоставления.

Например,

12-34 E. 5th street
APT 6B
City, ST 78910

будет соответствовать 12345678910. который вы можете реализовать с помощью чего-то вроде этого ...

select * FROM [table] 
WHERE regexp_replace(address_1 || address_2 || zip, '[^0-9]', '', 'g') = $addressNumbers;

дополнительно вы можете изучить расширения Postgres SoundEx,http://www.postgresql.org/docs/8.3/static/fuzzystrmatch.html, что может помочь упростить исправление изменений правописания, пробелов, пробелов, знаков пунктуации и т. Д.

...