在 PostgreSQL 函数中替代嵌套正则表达式替换?
Alternative to nesting regex replace in PostgreSQL functions?
现在,我有一个视图,其中包含一堆常见的条件字符串替换和开放文本字段的替换 - 在本例中为区域分类。
(请忽略地理的准确性,我只是在处理历史标准分配。另外,我知道我可以用 REPLACE 加快速度,甚至只是清理 RegEx 语句以供回顾 - 我我只是在这里询问 variable/nesting。)
CREATE OR REPLACE FUNCTION public.region_cleanup(record_region text)
RETURNS text
LANGUAGE sql
STRICT
AS $function$
SELECT REGEXP_REPLACE(
REGEXP_REPLACE(
REGEXP_REPLACE(
REGEXP_REPLACE(
REGEXP_REPLACE(
REGEXP_REPLACE(record_region,'(NORTH AMERICA\s\-\sUSA\s\-\sUSA)','USA')
,'Rest\sof\sthe\sWorld\s\-\s','')
,'NORTH\sAMERICA\s\-\sCANADA','NORTH AMERICA - Canada')
,'\&\;','&')
,'Georgia\s\-\sGeorgia','MIDDLE EAST - Georgia')
,'EUROPE - Turkey','MIDDLE EAST - Turkey')
使用此函数的示例输出在我的数据集中看起来像这样,提取受影响的记录(有些已经是正确的格式):
record_region_input
record_region_output
NORTH AMERICA - USA - USA - NORTHEAST - Massachusetts - Boston Metro
USA - NORTHEAST - Massachusetts - Boston Metro
NORTH AMERICA - USA - USA - MIDATLANTIC - Virginia
USA - MIDATLANTIC - Virginia
Rest of the World - ASIA - Thailand
ASIA - Thailand
Rest of the World - EUROPE - Portugal
EUROPE - Portugal
Rest of the World - ASIA - China - Shanghai Metro
ASIA - China - Shanghai Metro
Georgia - Georgia
MIDDLE EAST - Georgia
这...很好。正则表达式是必需的,因为在这些字符串之前或之后可能会出现大量可变性,并且我在其他地方有一个适当的验证列表。这只是对常见历史命名问题的批量清理。
问题是我从哪里得到了数百种此类“已知替代品”(100+),用于公司命名或跨部门标准等。拥有数十个 REGEXP_REPLACE(
嵌套语句使得 editing/adding/dropping 任何事情都成为令人抓狂的计数游戏。
我正在尝试专门清理 Postgres 中的数据,因为我当前的管道并不总是允许在上传之前进行标准化。我知道如何在纯 SQL 之外干净地解决这个问题,但是在 'vanilla' PostgreSQL 实例 (v12+) 中是否有更好的方法来转换视图的字符串?
使用示例函数更新了示例 input/output table。
如果您将一串数据拆分为其他区域,那么替换区域对您来说可能会很容易。例如:
with tb as (
select 1 as id, 'NORTH AMERICA - USA - USA - NORTHEAST - Massachusetts - Boston Metro' as record_region_input
union all
select 2 as id, 'NORTH AMERICA - USA - USA - MIDATLANTIC - Virginia'
union all
select 3 as id, 'Rest of the World - ASIA - China - Shanghai Metro'
)
select * from (
select distinct tb.id, unnest(string_to_array(record_region_input, ' - ')) as region from tb
order by tb.id
) a1 where a1.region not in ('NORTH AMERICA', 'Rest of the World');
-- Result:
1 Boston Metro
1 Massachusetts
1 NORTHEAST
1 USA
2 MIDATLANTIC
2 USA
2 Virginia
3 ASIA
3 China
3 Shanghai Metro
之后,例如,对于复制区域,您可以使用 distinct,对于不需要的区域,您可以使用 NOT in,并且您可以使用 like '%ASIA%' 来获取包含 ASIA
和等所有过程完成后,您可以再次合并更正后的字符串。示例:
with tb as (
select 1 as id, 'NORTH AMERICA - USA - USA - NORTHEAST - Massachusetts - Boston Metro' as record_region_input
union all
select 2 as id, 'NORTH AMERICA - USA - USA - MIDATLANTIC - Virginia'
union all
select 3 as id, 'Rest of the World - ASIA - China - Shanghai Metro'
)
select a1.id, string_agg(a1.region, ' - ') from (
select distinct tb.id, unnest(string_to_array(record_region_input, ' - ')) as region from tb
order by tb.id
) a1 where a1.region not in ('NORTH AMERICA', 'Rest of the World')
group by a1.id
-- Return:
1 Boston Metro - Massachusetts - NORTHEAST - USA
2 MIDATLANTIC - USA - Virginia
3 ASIA - China - Shanghai Metro
这是一个简单的想法,也许这个想法可以帮助您替换区域。
现在,我有一个视图,其中包含一堆常见的条件字符串替换和开放文本字段的替换 - 在本例中为区域分类。
(请忽略地理的准确性,我只是在处理历史标准分配。另外,我知道我可以用 REPLACE 加快速度,甚至只是清理 RegEx 语句以供回顾 - 我我只是在这里询问 variable/nesting。)
CREATE OR REPLACE FUNCTION public.region_cleanup(record_region text)
RETURNS text
LANGUAGE sql
STRICT
AS $function$
SELECT REGEXP_REPLACE(
REGEXP_REPLACE(
REGEXP_REPLACE(
REGEXP_REPLACE(
REGEXP_REPLACE(
REGEXP_REPLACE(record_region,'(NORTH AMERICA\s\-\sUSA\s\-\sUSA)','USA')
,'Rest\sof\sthe\sWorld\s\-\s','')
,'NORTH\sAMERICA\s\-\sCANADA','NORTH AMERICA - Canada')
,'\&\;','&')
,'Georgia\s\-\sGeorgia','MIDDLE EAST - Georgia')
,'EUROPE - Turkey','MIDDLE EAST - Turkey')
使用此函数的示例输出在我的数据集中看起来像这样,提取受影响的记录(有些已经是正确的格式):
record_region_input | record_region_output |
---|---|
NORTH AMERICA - USA - USA - NORTHEAST - Massachusetts - Boston Metro | USA - NORTHEAST - Massachusetts - Boston Metro |
NORTH AMERICA - USA - USA - MIDATLANTIC - Virginia | USA - MIDATLANTIC - Virginia |
Rest of the World - ASIA - Thailand | ASIA - Thailand |
Rest of the World - EUROPE - Portugal | EUROPE - Portugal |
Rest of the World - ASIA - China - Shanghai Metro | ASIA - China - Shanghai Metro |
Georgia - Georgia | MIDDLE EAST - Georgia |
这...很好。正则表达式是必需的,因为在这些字符串之前或之后可能会出现大量可变性,并且我在其他地方有一个适当的验证列表。这只是对常见历史命名问题的批量清理。
问题是我从哪里得到了数百种此类“已知替代品”(100+),用于公司命名或跨部门标准等。拥有数十个 REGEXP_REPLACE(
嵌套语句使得 editing/adding/dropping 任何事情都成为令人抓狂的计数游戏。
我正在尝试专门清理 Postgres 中的数据,因为我当前的管道并不总是允许在上传之前进行标准化。我知道如何在纯 SQL 之外干净地解决这个问题,但是在 'vanilla' PostgreSQL 实例 (v12+) 中是否有更好的方法来转换视图的字符串?
使用示例函数更新了示例 input/output table。
如果您将一串数据拆分为其他区域,那么替换区域对您来说可能会很容易。例如:
with tb as (
select 1 as id, 'NORTH AMERICA - USA - USA - NORTHEAST - Massachusetts - Boston Metro' as record_region_input
union all
select 2 as id, 'NORTH AMERICA - USA - USA - MIDATLANTIC - Virginia'
union all
select 3 as id, 'Rest of the World - ASIA - China - Shanghai Metro'
)
select * from (
select distinct tb.id, unnest(string_to_array(record_region_input, ' - ')) as region from tb
order by tb.id
) a1 where a1.region not in ('NORTH AMERICA', 'Rest of the World');
-- Result:
1 Boston Metro
1 Massachusetts
1 NORTHEAST
1 USA
2 MIDATLANTIC
2 USA
2 Virginia
3 ASIA
3 China
3 Shanghai Metro
之后,例如,对于复制区域,您可以使用 distinct,对于不需要的区域,您可以使用 NOT in,并且您可以使用 like '%ASIA%' 来获取包含 ASIA
和等所有过程完成后,您可以再次合并更正后的字符串。示例:
with tb as (
select 1 as id, 'NORTH AMERICA - USA - USA - NORTHEAST - Massachusetts - Boston Metro' as record_region_input
union all
select 2 as id, 'NORTH AMERICA - USA - USA - MIDATLANTIC - Virginia'
union all
select 3 as id, 'Rest of the World - ASIA - China - Shanghai Metro'
)
select a1.id, string_agg(a1.region, ' - ') from (
select distinct tb.id, unnest(string_to_array(record_region_input, ' - ')) as region from tb
order by tb.id
) a1 where a1.region not in ('NORTH AMERICA', 'Rest of the World')
group by a1.id
-- Return:
1 Boston Metro - Massachusetts - NORTHEAST - USA
2 MIDATLANTIC - USA - Virginia
3 ASIA - China - Shanghai Metro
这是一个简单的想法,也许这个想法可以帮助您替换区域。