雪花中的文本清理

问题描述 投票:0回答:1

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

#=============#==============#================#
| 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            |
+------------+------------+--------------+----------------+

我正在雪花中这样做。我知道如何在 postgres 中执行此操作(使用正则表达式拆分到表和 split_part 函数),但雪花不支持正则表达式拆分到表,因此我有点卡住了。任何帮助,将不胜感激。谢谢!

我尝试使用常规(不是正则表达式) split_to_table 函数来执行此操作,但显然结果不正确。我还尝试使用 object_construct 将文本转换为键值对,但将该文本转换为键值对也很困难

regex text snowflake-cloud-data-platform text-parsing
1个回答
0
投票

我认为 split() 或 split_to_table() 实际上是正确的方法,您只需要在事后进行一些操作即可。此查询并不能完全满足您的需求,因为我为案例陈述添加了一个额外的列,并且不包括原始记录,但这基于您提供的数据:

第一部分只是将

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';
© www.soinside.com 2019 - 2024. All rights reserved.