雪花我们如何遍历临时表的每一行并将其值插入到另一个表中,其中每个字段的值都是单行?

Posted

技术标签:

【中文标题】雪花我们如何遍历临时表的每一行并将其值插入到另一个表中,其中每个字段的值都是单行?【英文标题】:Snowflake how can we loop over each row of a temp table and insert its values with into another table where each field with its value is a single row? 【发布时间】:2021-03-01 07:41:58 【问题描述】:

我们正在将数据加载到事实表中,我们在 Snowflake 上的原始临时表如下所示:

indicator_nbr 字段是调查中提出的问题。

我们正在使用数据建模技术来构建我们的仓库数据库,因此数据将被添加到事实表中,如下所示:

如果还有其他问题,则对指标 2 和 3 以此类推。

每个字段及其值将作为一行。当然还有其他元数据要添加,例如load_dtrecord_src,但它们不是问题。

当前脚本正在执行以下操作:

    将字段放入数组 => fields_array = ['indicator_1', 'indicator_2', 'indicator_3']

    一个循环将在数组上运行,并开始为每一行添加每个字段及其值。所以假设我们有 100 行,我们将运行 300 次插入,一次一个:

    for (var col_num = 0; col_num<fields_array.length; col_num = col_num+1)

        var COL_NAME = fields_array[col_num];
    
        var field_value_query = "INSERT INTO SAT_FIELD_VALUE SELECT md5(id), CURRENT_TIMESTAMP(), NULL, 'SRC', "+COL_NAME+", md5(foreign_key_field) FROM "+TEMP_TABLE_NAME+"";
    

正如在this post 上的评论中提到的,显示了完整的脚本,最好循环连接插入查询的每个from values 的字符串。

建议的解决方案有 2 个问题:

    Snowflake 上的查询有大小限制(应小于 1 MB); 如果我们要遍历每个字段并连接from values,我们也应该从临时表中执行select 查询以获取列的值,因此不会进行优化,或者我们会减少一点时间,但不会太多。

编辑:可能的解决方案

我正在考虑做一个 sql 查询,从临时表中选择所有内容,然后对所有内容进行哈希处理,然后在转置后将其保存到一个数组中,但我不知道该怎么做。

【问题讨论】:

您应该能够在单个 SQL 命令中执行此操作,例如 insert into [table] select * from。不知道为什么需要为此在 java 中构建一堆插入语句?如果需要将列转置为行,可以使用unpivot SQL 函数。 【参考方案1】:

不确定这是否是您要查找的内容,但您似乎只是想做一个支点:

设置示例场景

create or replace transient table source_table
(
    id          number,
    indicator_1 varchar,
    indicator_2 number,
    indicator_3 varchar
);

insert overwrite into source_table
values (1, 'Test', 2, 'DATA'),
       (2, 'Prod', 3, 'DATA'),
       (3, 'Test', 1, 'METADATA'),
       (4, 'Test', 1, 'DATA')
;

create or replace transient table target_table
(
    hash_key varchar,
    md5      varchar
);

运行插入

select
    name_col as hash_key,
    md5(id)
from (select
          id,
          indicator_1,
          indicator_2::varchar as indicator_2,
          indicator_3
      from source_table) unpivot ( val_col for name_col in (indicator_1, indicator_2, indicator_3))
;

这会产生一个如下所示的 target_table:

+-----------+--------------------------------+
|HASH_KEY   |MD5                             |
+-----------+--------------------------------+
|INDICATOR_1|c4ca4238a0b923820dcc509a6f75849b|
|INDICATOR_2|c4ca4238a0b923820dcc509a6f75849b|
|INDICATOR_3|c4ca4238a0b923820dcc509a6f75849b|
|INDICATOR_1|c81e728d9d4c2f636f067f89cc14862c|
|INDICATOR_2|c81e728d9d4c2f636f067f89cc14862c|
|INDICATOR_3|c81e728d9d4c2f636f067f89cc14862c|
|INDICATOR_1|eccbc87e4b5ce2fe28308fd9f2a7baf3|
|INDICATOR_2|eccbc87e4b5ce2fe28308fd9f2a7baf3|
|INDICATOR_3|eccbc87e4b5ce2fe28308fd9f2a7baf3|
|INDICATOR_1|a87ff679a2f3e71d9181a67b7542122c|
|INDICATOR_2|a87ff679a2f3e71d9181a67b7542122c|
|INDICATOR_3|a87ff679a2f3e71d9181a67b7542122c|
+-----------+--------------------------------+

【讨论】:

我可以把这个select 放在when not matchedinsert 子句中吗? 你的意思是合并语句吗?是的。 我在这个查询中有一个问题,我发布了一个新问题:***.com/questions/66424515/…【参考方案2】:

使用INSERT ALL的场景很棒:

INSERT ALL
INTO dst_tab(hash_key, md5) VALUES (indicator_1, md5)
INTO dst_tab(hash_key, md5) VALUES (indicator_2, md5)
INTO dst_tab(hash_key, md5) VALUES (indicator_3, md5) 
SELECT MD5(id) AS md5, indicator_1, indicator_2::STRING AS indicator_2, indicator_3 
FROM src_tab;

【讨论】:

以上是关于雪花我们如何遍历临时表的每一行并将其值插入到另一个表中,其中每个字段的值都是单行?的主要内容,如果未能解决你的问题,请参考以下文章

如何循环遍历表的所有行? (MySQL)

SQL 从临时表插入表,并将输出插入临时表

MySQL存储过程循环遍历变量并插入临时表

在表格的每一行中插入一个随机数

使用雪花中的合并将值插入表并根据条件删除行

如何使用 for 循环选择字段值并将它们插入到另一个表中