在 oracle sql 中使用 regexp_replace 标准化地址
Posted
技术标签:
【中文标题】在 oracle sql 中使用 regexp_replace 标准化地址【英文标题】:Standardizing addresses using regexp_replace in oracle sql 【发布时间】:2021-02-22 21:05:50 【问题描述】:非常感谢大家的帮助。
我们正在标准化我们客户的地址。
我有一个包含客户数据的主客户表,地址字段要标准化。
我有一个映射表,其中包含从 from_str 到 to_str 值的映射。
我需要将from_str对应的to_str放入地址数据中。
如果标准化后地址的长度超过35个字符,则从字符串右侧到末尾的前一个空格('')创建为单独的字段地址2
你能帮忙处理一下 sql 或 pl/sql 吗?使用 Oracle 12c 数据库。
我在下面编写的代码不适用于所有 from_str 值...仅适用于前 2 行。
感谢任何帮助。
到目前为止的代码:
with addresses as
(
select cust_id,address addr from
(
select 10 cust_id,'9 Help Street, Level 4' address from dual union all
select 11 cust_id,'22 Victoria Street' address from dual union all
select 12 cust_id,'1495 Franklin Str' address from dual union all
select 13 cust_id,'30 Hasivim St.,Petah-Tikva' address from dual union all
select 14 cust_id,'2 Jakaranda St' address from dual union all
select 15 cust_id,'61, Science Park Rd' address from dual union all
select 16 cust_id,'61, Social park road' address from dual union all
select 17 cust_id,'Av. Hermanos Escobar 5756' address from dual union all
select 18 cust_id,'Ave. Hermanos Escobar 5756' address from dual union all
select 19 cust_id,'8000 W FLORISSANT AVE' address from dual union all
select 20 cust_id,'8600 MEMORIAL PKWY SW' address from dual union all
select 21 cust_id,'8200 FLORISSANTMEMORIALWAYABOVE SW' address from dual union all
select 22 cust_id,'8600 MEMORIALFLORISSANT PKWY SW' address from dual
) t1
),
replacements as
(
select id,to_str,from_string from_str from
(
select 1 id,'St' to_str,'Street' from_string from dual union all
select 2 id,'St' to_str,'St.' from_string from dual union all
select 3 id,'St' to_str,'Str' from_string from dual union all
select 4 id,'St' to_str,'St' from_string from dual union all
select 5 id,'Rd' to_str,'Rd.' from_string from dual union all
select 6 id,'Rd' to_str,'road' from_string from dual union all
select 7 id,'Av' to_str,'Av.' from_string from dual union all
select 8 id,'Av' to_str,'Ave.' from_string from dual union all
select 9 id,'Av' to_str,'Avenue' from_string from dual union all
select 10 id,'Av' to_str,'Aven.' from_string from dual union all
select 11 id,'West' to_str,'W' from_string from dual union all
select 12 id,'South West' to_str,'SW.' from_string from dual
) t2
),
r(addr,test_addr,l) as
(
select addr,regexp_replace(addr,'(^|\W)' || from_str || '(\W|$)','\1' || to_str || '\2') test_addr,
id - 1
from
addresses,
replacements
where id = (select count(*) from replacements)
union all
select addr,regexp_replace(addr,'(^|\W)' || from_str || '(\W|$)','\1' || to_str || '\2') test_addr,
l - 1
from r,
replacements
where id = l
)
select addr,test_addr,l
from r
where l=0
;
预期输出:
cust_id address
10 9 Help St, Level 4
11 22 Victoria St
12 1495 Franklin St
13 30 Hasivim St ,Petah-Tikva
14 2 Jakaranda St
15 61, Science Park Rd
16 61, Social park Rd
17 Av Hermanos Escobar 5756
18 Av Hermanos Escobar 5756
19 8000 West FLORISSANT Ave
20 8600 MEMORIAL PKWY South West
如果地址长度超过 35 个字符,则预期输出为:
cust_id address address2
21 8200 FLORISSANTMEMORIALWAYABOVE South West
22 8600 MEMORIALFLORISSANT PKWY South West
【问题讨论】:
如果能提供一些样本数据和想要的结果就更好了。 @PavelSmirnov,我已经在查询中提供了示例数据,并在我的问题中给出了预期的输出,谢谢 【参考方案1】:这是一种应用多个替换操作的有趣方式。所以 - 正如你所提到的,你有两个问题。对于第一个,CTE 的递归部分是在 addr
上执行 regexp_replace()
而不是 test_addr
(上一个递归步骤的修改输出)。所以只应用列表中的最后一条规则。
r(addr,test_addr, l) as
(
select addr,regexp_replace(addr,'(^|\W)' || from_str || '(\W|$)','\1' || to_str || '\2') test_addr,
id - 1
from
addresses,
replacements
where id = (select count(*) from replacements)
union all
-- if you do regexp_replace on addr, it throws out the previous replace (which is in r.test_addr)
select addr,regexp_replace(test_addr,'(^|\W)' || from_str || '(\W|$)','\1' || to_str || '\2') test_addr,
l - 1
from r,
replacements
where id = l
)
对于“超过 35 个字符”的问题,我建议使用 substr/instr - 虽然难以阅读,但它们通常很快。
select addr,test_addr,l,
case when length(test_addr) > 35 then
substr(test_addr, 1, instr(substr(test_addr,1,35), ' ', -1))
else test_addr
end as addr1,
case when length(test_addr) > 35 then
substr(test_addr, instr(substr(test_addr,1,35), ' ', -1))
else null
end as addr2
from r
where l=0
;
可能有一种更优雅的方式来完成这部分,这只是我想到的第一件事。
【讨论】:
非常感谢。第一个查询有效。超过 35 个字符的查询,一个小故障,我会调查一下。 我尝试了您的查询,但不适用于所有场景...这里有一个场景不起作用..您能帮忙吗? 该查询不适用于某些国家/地区,但适用于某些国家...我发布了一个标题为“标准化地址,sql 不起作用”的新帖子..您能帮忙吗?跨度>以上是关于在 oracle sql 中使用 regexp_replace 标准化地址的主要内容,如果未能解决你的问题,请参考以下文章
Oracle 12c - 在 REST 调用中使用动态 SQL