sql - 地址/邮政编码和电话的部分/匹配的复杂查询帮助

标签 sql postgresql query-optimization

示例数据:

$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, SIMILARCITEXTFTS (Free Text Search) 所有这些都很棒,但我不确定如何实现它们以获得我想要的结果。 我不介意为每个查询运行多个查询,例如查询 $address_1 匹配项和另一个查询 $address_2 匹配项等等。我也知道会有误报和漏报,但我希望准确率达到 75% 左右(或更高)。

一个重要注意事项是 Postgres 服务器正在运行7.4 版,并且没有升级计划。

还有多个address_1address_2zipphone (为家庭和办公室考虑单独的地址/电话)

这是我第一次尝试解决这个问题:

我有一个想法来生成最常见的格式,然后将它们作为查询中的参数传递。

类似于:

$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 问题 #2)

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

使用 UNION 方法(来自 Stack 问题 #1)进行每个添加地址字段搜索,例如 Office 和 Home

最佳答案

如果我理解正确,您需要从一个字段到另一个字段进行零碎匹配(例如,“123”匹配“123-111”和“12345”,但不匹配“122234”或“122-345”)并且您需要避免所有匹配时的符号。这是正确的吗?

下面的伪代码是我首先要尝试的:

  • 处理所有输入字段以删除符号
  • 标记字段以确定要匹配的片段
  • 将片段与数据值进行匹配

听起来最好的实现方式是通过 ILIKE 查询,其中百分号是片段的开头和结尾,例如:

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

您将不得不多次执行此查询,这可能会给性能带来麻烦,但我相信这可能会让您得到想要的结果。

关于sql - 地址/邮政编码和电话的部分/匹配的复杂查询帮助,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4762105/

相关文章:

sql - 我想以分层形式生成 XML 文件

ruby-on-rails - Postgresql:致命:用户 "rooms"的密码身份验证失败

mysql - 查询成本是 MySQL 查询优化的最佳指标吗?

postgresql - 为 PostgreSQL hot_standby 设置 wal_keep_segments

postgresql - Postgres ODBC 驱动脚本安装

MySQL 查询需要优化

Oracle 相当于 SQLite 的 quote() 函数

mysql - SQL按类别平均列

c# - 如何检查数据库可用性

c++ - 使用 OTL 库从 C++ 程序将数据插入 mysql 表