地址/邮编和电话部分/匹配的复杂查询帮助
Posted
技术标签:
【中文标题】地址/邮编和电话部分/匹配的复杂查询帮助【英文标题】:Complex query help for Partial/Match on Address/Zip and Phone 【发布时间】:2011-01-21 17:55:55 【问题描述】:示例数据:
$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'
这可以是单独的查询,但我需要在地址中搜索部分匹配项,并在手机中搜索 zip 和完整匹配项。
所以
$address_1
将部分匹配 record_id
123 作为 '123 Main St.'是“123 main street”的变体$address_2
将匹配 record_id
124,因为“Suite 200”是“Suite #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 (Free Text Search),所有这些都很棒,但我不确定如何实施它们以获得我想要的结果。
我不介意为每个查询运行多个查询,例如查询 $address_1
匹配和另一个查询 $address_2
匹配等等。我也知道会有误报和误报,但我希望准确率能达到 75% 左右(或更高)。
一个重要注意事项是 Postgres 服务器正在运行 7.4 版,并且没有升级计划。
为了增加查询的复杂性,还有多个address_1
、address_2
、zip
和phone
(请考虑单独的地址/电话,例如家庭和办公室)
这是我第一次尝试解决这个问题:
Stack Question #1 Stack Question #2我有一个想法来生成最常见的格式,然后将它们作为参数传递给查询。
类似:
$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%'
)
似乎我必须做出很多变化,但我仍然不确定这是否是最佳方式。
更新:
这有点工作(来自堆栈问题 #2)
SELECT *
FROM tbl_name
WHERE LOWER(address_1) ILIKE LOWER('123 Main%')
使用 UNION 方法(来自 Stack Question #1)对每个添加地址字段搜索,如 Office 和 Home
【问题讨论】:
【参考方案1】:如果我的理解正确,您需要从字段到字段的片段匹配(例如,“123”匹配“123-111”和“12345”,但不匹配“122234”或“122-345”),您需要避免所有匹配时的符号。这样正确吗?
下面的伪代码是我首先要尝试的:
处理所有输入字段以删除符号 标记字段以确定要匹配的片段 对数据值执行片段匹配听起来最好的方法是通过 ILIKE 查询,其中百分号是片段的开头和结尾,例如:
SELECT * FROM [TABLE_NAME] WHERE address_1 ILIKE '%fragment%'
您必须多次执行此查询,这可能会导致性能问题,但我相信这可能会得到您想要的。
【讨论】:
好吧,它们的符号可能已经在数据库中,所以我需要匹配它们。或者数据库中可能缺少符号,因此如果通过,我需要删除它们。我也没有什么可以用作过滤大约 8000 条记录的结果的条件。 @Phill:在 ilike 子句旁边使用三元组条件来预过滤结果:postgresql.org/docs/current/static/pgtrgm.html【参考方案2】:我有一些方法建议。
我强烈考虑从电话号码中删除所有非数字。 你可以在 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 这可能有助于简化拼写变化、大小写、间距、标点符号等的更正。
【讨论】:
有趣的方法。一个注意事项是我在 Postgres 7.4 上运行,我不确定第二个选项是否可用。仍然会有一些误报,但匹配数字字符串可能是一个可靠的解决方案。 +1 开箱即用,我将不得不尝试这个。谢谢 错误:函数 regexp_replace(text, "unknown", "unknown", "unknown") 不存在 提示:没有函数匹配给定的名称和参数类型。您可能需要添加显式类型转换。 哦,抱歉,7.4 不支持 regexp_ 字符串函数,你可能需要在 plperl 中实现自己的函数。以上是关于地址/邮编和电话部分/匹配的复杂查询帮助的主要内容,如果未能解决你的问题,请参考以下文章