我有一个带有 VARIANT 列的表,其中包含来自 Snowpipe 的 XML。我能够使用 XMLGET 和 GET 的奇怪组合来解析大多数字段的 XML。但是,有一个字段是一个数组,我只能提取标签值数组中的第一个值。每个记录在标记数组中可以有 0 - 100 个值,因此我需要足够动态的内容来涵盖所有这些场景。我花了几天时间试图解决这个问题,但我被难住了。
这里有一些命令可帮助复制我的问题以及具有部分(但不是全部)值的查询。请注意,这个查询将在 dbt 中使用,定期将数据从 XML 转换为表格,其中有数百万行进入,所以我也想在这个解析中考虑性能...我很好奇是否有人有比嵌套 XMLGET 命令更好的方法。我将在帖子底部添加所需的输出。
预先感谢任何可以帮助我的人!
create temp table if not exists temp_cf_final (RECORD_CONTENT variant);
insert into temp_cf_final
select parse_xml('<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<?opentarget version=\"1.1\"?>\n<opentarget xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n<txn id=\"20339559598\" msgIdx=\"76\" msgTot=\"86\" commitTime=\"2023-09-28T10:54:44\" userId=\"349\" oracleTxnId=\"122.17.359225\" />\n<tbl name=\"MAROON_DEV.CF_FINAL\">\n<cmd ops=\"upd\">\n<row id=\"AAIjTAAA7AAHuvTAAZ\">\n<col name=\"DATA\" type=\"varray\" />\n<varray>\n<value>1 street</value>\n<value> </value>\n<value></value>\n<value>Nashville</value>\n<value>TN</value>\n<value>37211</value>\n<value></value>\n</varray>\n<lkup>\n<col name=\"CF_FINAL_ID\">14773</col>\n</lkup>\n</row>\n</cmd>\n</tbl>\n</opentarget>\n');
insert into temp_cf_final
select parse_xml('<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<?opentarget version=\"1.1\"?>\n<opentarget xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n<txn id=\"20339559598\" msgIdx=\"77\" msgTot=\"86\" commitTime=\"2023-09-28T10:54:44\" userId=\"349\" oracleTxnId=\"122.17.359225\" />\n<tbl name=\"MAROON_DEV.CF_FINAL\">\n<cmd ops=\"upd\">\n<row id=\"AAIjTAAA7AAHuvTAAa\">\n<col name=\"DATA\" type=\"varray\" />\n<varray>\n<value>2486</value>\n</varray>\n<lkup>\n<col name=\"CF_FINAL_ID\">14774</col>\n</lkup>\n</row>\n</cmd>\n</tbl>\n</opentarget>\n');
select record_content
,TO_TIMESTAMP(GET(XMLGET(PARSE_XML(RECORD_CONTENT),'txn'),'@commitTime')) as last_commit_time
,GET(XMLGET(XMLGET(PARSE_XML(RECORD_CONTENT),'tbl'),'cmd'),'@ops')::string as last_operation
,CASE
WHEN LAST_OPERATION='ins' THEN GET(XMLGET(XMLGET(XMLGET(XMLGET(PARSE_XML(RECORD_CONTENT),'tbl'),'cmd'),'row'),'col',0),'$')
WHEN LAST_OPERATION='upd' THEN GET(XMLGET(XMLGET(XMLGET(XMLGET(XMLGET(PARSE_XML(RECORD_CONTENT),'tbl'),'cmd'),'row'),'lkup'),'col',0),'$')
END::number AS CF_FINAL_ID
,SUBSTR(GET(XMLGET(PARSE_XML(RECORD_CONTENT),'tbl'),'@name'),1,CHARINDEX('.',GET(XMLGET(PARSE_XML(RECORD_CONTENT),'tbl'),'@name'))-1)::string AS CUSTOMER_SCHEMA
,GET(XMLGET(XMLGET(XMLGET(XMLGET(PARSE_XML(RECORD_CONTENT),'tbl'),'cmd'),'row'),'varray'),'$') as DATA_UPD --Works to get me either the single value of "value" or the array of values
,regexp_substr_all(GET(XMLGET(XMLGET(XMLGET(XMLGET(PARSE_XML(RECORD_CONTENT),'tbl'),'cmd'),'row'),'varray'),'$'),$$"\$":\w+$$,1,1) as DU_values --Works on the array of values, but only pulls the last in the array
,GET(XMLGET(XMLGET(XMLGET(XMLGET(XMLGET(PARSE_XML(RECORD_CONTENT),'tbl'),'cmd'),'row'),'varray'),'value'),'$')::VARCHAR as DU_first_line --Works great to get the single value, but returns only the first line of an array of values
from temp_cf_final;
从上面可以看出...
DATA_UPD 列提供了奇异值和值数组。 DU_FIRST_LINE 更进一步,生成我想要的奇异值 VARCHAR,但只给出值数组的第一行。 DU_VALUES 是我尝试通过正则表达式从数组中获取值,但经过几个小时的尝试后,这对我来说是行不通的。
我想看到的 DATA 是值 string_agg'd 和逗号分隔的数组(一旦我/我们/你弄清楚了数组解析,我就可以这样做)?
CF_FINAL_ID |数据
14773 | 1 号街,纳什维尔,田纳西州,37211, 14774 | 2486