在oracle sql中使用regexp_replace标准化地址
我真的很感谢你们的帮助 我们正在对客户地址进行标准化 我有一个主客户表,其中包含客户数据、要标准化的地址字段 我有一个映射表,其中包含从\u str到\u str值的映射 我需要将与from_str相对应的to_str输入地址数据 如果标准化后的地址长度超过35个字符,则从字符串右侧到末尾的上一个空格(“”)将创建为单独的字段address2 您能帮我学习sql或pl/sql吗?使用oracle12c数据库 我在下面编写的代码不适用于所有from_str值…只适用于前两行 感谢您的帮助 迄今为止的代码:在oracle sql中使用regexp_replace标准化地址,sql,oracle,plsql,oracle12c,Sql,Oracle,Plsql,Oracle12c,我真的很感谢你们的帮助 我们正在对客户地址进行标准化 我有一个主客户表,其中包含客户数据、要标准化的地址字段 我有一个映射表,其中包含从\u str到\u str值的映射 我需要将与from_str相对应的to_str输入地址数据 如果标准化后的地址长度超过35个字符,则从字符串右侧到末尾的上一个空格(“”)将创建为单独的字段address2 您能帮我学习sql或pl/sql吗?使用oracle12c数据库 我在下面编写的代码不适用于所有from_str值…只适用于前两行 感谢您的帮助 迄今为止
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
那是一个。。。应用多个替换操作的有趣方法。正如你提到的,你有两个问题。对于第一个,CTE的递归部分是在
addr
上执行regexp\u replace()
,而不是test\u 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
;
也许有一种更优雅的方式来完成这一部分,这只是我想到的第一件事。这是一个。。。应用多个替换操作的有趣方法。正如你提到的,你有两个问题。对于第一个,CTE的递归部分是在
addr
上执行regexp\u replace()
,而不是test\u 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
;
可能有一种更优雅的方式来完成这一部分,这只是我想到的第一件事。如果你能提供一些样本数据和期望的结果,那就更好了。@PavelSmirnov,我已经在查询中提供了样本数据,并在我的问题中给出了预期的输出,谢谢如果你能提供一些样本数据和期望的结果,那就更好了。@PavelSmirnov,我已经在中提供了样本数据和查询,并在我的问题中给出了预期的结果,非常感谢。第一个查询有效。超过35个字符的查询,一个小故障,我会调查一下。我尝试了你的查询,但不适用于所有场景…这里有一个场景不适用。。你能帮忙吗。这个查询对某些国家不起作用,但对某些国家有效……我作为一个新帖子发布,标题是“地址标准化,sql不起作用”。你能帮忙吗?非常感谢。第一个查询有效。超过35个字符的查询,一个小故障,我会调查一下。我尝试了你的查询,但不适用于所有场景…这里有一个场景不适用。。你能帮忙吗。这个查询对某些国家不起作用,但对某些国家有效……我作为一个新帖子发布,标题是“地址标准化,sql不起作用”。你能帮忙吗?