regex Snowflake中的文本清理

vnzz0bqm  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(70)

我有一个表中的列,其中包含有关以下格式的公司变更相关的任何更新的数据-

#=============#==============#================#
| Company ID  |  updated_at  |   updates      |
#=============#==============#================#
| 101         | 2020-11-01   | name:          |
|             |              | -ABC           |
|             |              | -XYZ           |
|             |              | url:           |
|             |              | -www.abc.com   |
|             |              | -www.xyz.com   |
+-------------+--------------+----------------+
| 109         | 2020-10-20   | rating:        |
|             |              | -4.5           |
|             |              | -4.0           |
+-------------+--------------+----------------+

正如您在上面所看到的,列updates包含的字符串包括换行符,并描述了一个或多个更新。在上面的示例中,这意味着对于公司ID 101,名称从ABC更改为XYZ,URL从www.abc.com更改为www.xyz.com。对于公司ID 109,只有评级从4.5更改为4.0。
然而,我想把更新列分为3列-一个应该包含什么改变(网址,名称等),第二个应该有旧的值和第三列应该有新的值。像这样的-

#============#============#==============#================#
| Company ID |   Field    |  Old Value   |   New Value    |
#============#============#==============#================#
| 101        |   name     | ABC          | XYZ            |
+------------+------------+--------------+----------------+
| 101        |   url      | www.abc.com  | www.xyz.com    |
+------------+------------+--------------+----------------+
| 109        |   rating   | 4.5          | 4.0            |
+------------+------------+--------------+----------------+

我在Snowflake做这个。我知道如何在postgres中做到这一点(使用regexp split to table和split_part函数),但snowflake不支持regexp split to table,因此我有点卡住了。如果你能帮忙的话,我将不胜感激。谢谢你,谢谢
我尝试使用一个常规的(而不是regexp)split_to_table函数来实现这一点,但显然结果不正确。我还尝试使用object_construct将文本转换为键值对,但将文本转换为键值对也很困难

eqfvzcg8

eqfvzcg81#

我认为split()或split_to_table()实际上是正确的方法,你只需要在事后做一些操作。这个查询并不能得到你所需要的,因为我为我的case语句添加了一个额外的列,并且不包括原始记录,但是这个查询基于你提供的数据工作:
第一部分只是将updates字段复制到一列中:

with x as (
select 'name:
-ABC
-XYZ
url:
-www.abc.com
-www.xyz.com'::string as str
)

使用下面横向扁平化中的分割,然后我可以使用lead()函数来获取接下来的2条记录(旧值和新值)。这假设您的格式在每个记录中是一致的,但确实像您上面描述的那样工作:

select trim(y.value::string,'-,:') as field, 
       case when right(value,1) = ':' then 'name' else 'value' end as field_type,
       case when field_type = 'name' then
           lead(field,1) over (partition by seq order by index)
       end as old_value,
       case when field_type = 'name' then
           lead(field,2) over (partition by seq order by index)
       end as new_value
from x,
lateral flatten(input=>split(str,'\n')) y
qualify field_type = 'name';

相关问题