现在,我有了一个视图,其中有一堆常见的、有条件的字符串替换和对开放文本字段的替换——在本例中是区域分类.

(Please ignore the accuracy of geography, I'm just working with historical standard assignments. Also, I know I could speed things up with REPLACE or even just cleaning the RegEx statements for lookback - I'm just asking about the variable/nesting here.)

    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')
            ,'\&amp\;','&')
            ,'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

这是...好的正则表达式是必需的,因为在这些字符串之前或之后可能会出现大量的变化,我在其他地方有一个适当的验证列表.这只是一些常见的历史命名问题.

The problem is where I get hundreds of these kind of "known substitutions" (100+)用于公司命名或跨部门标准.有几十个REGEXP_REPLACE(个嵌套语句,使得编辑/添加/删除任何内容都成为一个疯狂的计数游戏.

我正在try 只清理Postgres中的数据,因为我目前的管道并不总是允许在上传之前进行标准化.我知道如何在纯SQL之外清晰地解决这个问题,但在"普通"PostgreSQL实例(v12+)中,有没有更好的方法来转换视图的字符串?

Updated with a sample input/output table using the example function.

推荐答案

如果您将一串数据拆分为其他区域,那么替换区域对您来说可能很容易.例如:

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,并且您可以使用像"%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

这是一个简单的 idea ,也许这个 idea 可以帮助你替换区域.

Postgresql相关问答推荐

优化PostgreSQL查询以将用户插入数据库

DBT-DBT依赖于未找到的源

返回行值和行计数的总和

IF 块中的 CREATE FUNCTION 语句抛出错误,同时运行它自己的作品

将数组的所有元素循环到jsonb中并修改值

连接到 PostgreSQL 时没有属性执行错误

Postgres 转储按顺序插入

PostgreSQL - 我应该如何使用 first_value()?

在 Ubuntu 11.04 服务器中启用对 postgresql 的 PHP 支持

PostgreSQL 在 mySQL 中的 date_trunc

冲突中的 Postgres 会更新复合主键

如何将 DELETE 的返回值插入到 postgresql 中的 INSERT 中?

如何在构建时链接 docker 容器?

如果 PostgreSQL 数据库中存在,则删除表

无法识别的配置参数bytea_output

获取全文搜索配置语言的完整列表

Hibernate 启动很慢

如何使用 PostgreSQL 触发器来存储更改(SQL 语句和行更改)

如何使 array_agg() 像 mySQL 中的 group_concat() 一样工作

在子类的 Hibernate 中 for each 表指定不同的序列