目前,我已暂存 5 个文件,但都缺少一个列标题:
2021 | 2022 | 2023 | |
---|---|---|---|
A组 | 54.9 | 55.3 | 55.7 |
B组 | 91.3 | 82.7 | 89.6 |
我无法更改这些文件的格式。我在 Snowflake 中使用了 infer_schema 函数,因为随着添加更多年份列,文件将是动态的。
这就是我想尝试的:
Create or replace table staging_table
using template (
select array_agg(object_construct(*))
from table(
infer_schema(
location => 'stage'
file_format => 'file_format'
)
)
);
copy into staging_table
from @stage
file_format = 'file_format'
match_by_column_name = case_insensitive;
我正在使用临时表,因为我还想取消数据透视。我最初在 file_format 中使用了
parse_header = true
,但由于缺少标头而不起作用。我尝试过 parse_header = false
但这使得跟踪列并重命名它们变得更加困难(日期列比示例中的列更多)。有人知道如何更好地处理此案吗?
另外,我知道这可能会很长,但我也想获取表中的文件名。我知道我可以得到这样的文件名:
SELECT *
FROM TABLE (
INFER_SCHEMA(
LOCATION => MY_STAGE,
FILE_FORMAT => 'MY_FILE_FORMAT'
)
);
但是我如何实际将数据与数据一起插入/复制到我的临时表中?
换句话说,我想要 Snowflake 中的数据如下:
团体 | 年份 | 分数 | 文件名 |
---|---|---|---|
A组 | 2021 | 54.9 | 文件1 |
A组 | 2022 | 55.7 | 文件1 |
A组 | 2023 | 55.7 | 文件1 |
A组 | 2021 | 33.1 | 文件2 |
A组 | 2022 | 33.1 | 文件2 |
A组 | 2023 | 34.2 | 文件2 |
如何在 Snowflake 中从第一种文件格式转换为第二种表格格式?
任何帮助将不胜感激!我是否必须将其分成 5 个不同的暂存表,然后对真实表进行一次大插入?
要使其发挥作用,方法是:
首先,创建一种读取整行而不是单个字段的文件格式:
create or replace file format READ_LINE type = csv
field_delimiter = 'NONE' compression = 'AUTO';
然后,您可以通过执行选择来确保这可以读取整行:
select metadata$file_row_number, metadata$filename, $1 as LINE
from @MY_FILES (file_format => READ_LINES);
接下来,创建 UDTF 来处理数据如何到达文件:
create or replace function PIVOT_SCORES(LINE_NUMBER float, FILENAME string, LINE string)
returns table (GROUP_NAME string, YEAR string, SCORE string)
language javascript strict immutable
as
$$
{
initialize: function (argumentInfo, context) {
this.years = [];
},
processRow: function (row, rowWriter, context) {
var lineYear;
var lineItems;
if(row.LINE_NUMBER == 1) {
if(row.LINE.trim().substr(0,1) == ",") {
this.years = row.LINE.trim().substr(1).split(",");
} else {
this.years = row.LINE.trim().split(",");
}
} else {
lineItems = row.LINE.trim().split(",");
for (let i=1; i < lineItems.length; i++) {
rowWriter.writeRow({GROUP_NAME:lineItems[0],YEAR:this.years[i-1],SCORE:lineItems[i]});
}
}
},
finalize: function (rowWriter, context) { /* */ },
}
$$
;
最后,选择文件中的行并通过 UDTF 运行它们,如下所示:
with FILE_LINES as
(
select metadata$file_row_number LINE_NUMBER
,metadata$filename FILE_NAME
,$1 LINE
from @MY_FILES (file_format => READ_LINES) F
)
select GROUP_NAME
,YEAR
,SCORE
,FILE_NAME
from FILE_LINES F
,table(pivot_scores(LINE_NUMBER::float, FILE_NAME, F.LINE) over (partition by FILE_NAME order by LINE_NUMBER)) TF
;
我创建了两个文件来测试这一点。 File1 是基于示例表的文件,File2 是一个新文件,带有额外的一年(2020 年)用于测试。这是结果:
GROUP_NAME | 年份 | 得分 | FILE_NAME |
---|---|---|---|
A组 | 2020 | 54.9 | 文件2.txt.gz |
A组 | 2021 | 55.3 | 文件2.txt.gz |
A组 | 2022 | 55.7 | 文件2.txt.gz |
A组 | 2023 | 11.1 | 文件2.txt.gz |
B组 | 2020 | 91.3 | 文件2.txt.gz |
B组 | 2021 | 82.7 | 文件2.txt.gz |
B组 | 2022 | 89.6 | 文件2.txt.gz |
B组 | 2023 | 11.1 | 文件2.txt.gz |
C组 | 2020 | 12.3 | 文件2.txt.gz |
C组 | 2021 | 12.3 | 文件2.txt.gz |
C组 | 2022 | 12.4 | 文件2.txt.gz |
C组 | 2023 | 11.1 | 文件2.txt.gz |
A组 | 2021 | 54.9 | 文件1.txt.gz |
A组 | 2022 | 55.3 | 文件1.txt.gz |
A组 | 2023 | 55.7 | 文件1.txt.gz |
B组 | 2021 | 91.3 | 文件1.txt.gz |
B组 | 2022 | 82.7 | 文件1.txt.gz |
B组 | 2023 | 89.6 | 文件1.txt.gz |