根据来自另一个 table 的数据在 FOR 循环中执行 Snowflake SQL 查询
Perform Snowflake SQL queries in FOR LOOP based on data from another table
在 Snowflake 中,我正在尝试创建一个带有 for 循环的 SQL 脚本,该脚本根据 data_type 列
将结果输出到新的 table ]
我有一个名为 PROFILE_TABLE_LIST 的 table,其中的列带有
table名称和列名,以及数据类型如下所示:
TABLENAME
COLUMN_NAME
DATA_TYPE
Table1
PLANTS
TEXT
Table1
HEIGHT
FLOAT
Table2
COLOR
TEXT
Table2
SMELL
TEXT
我目前正在尝试使用游标执行 for 循环并对每一行执行查询以根据列类型分析 table 看起来像这样:
TABLENAME
COLUMN_NAME
DATA_TYPE
COUNT
MAX_LENGTH
MAX_VALUE
Table1
PLANTS
TEXT
10
82
NULL
Table1
HEIGHT
FLOAT
10
NULL
58.6
Table2
COLOR
TEXT
20
56
NULL
Table2
SMELL
TEXT
20
23
NULL
最终,我想 运行 不同的 select 语句以 data_type 为条件,但在这个阶段,我只关注计数。这是我的当前循环。但是,select 语句未正确执行,因为 table 名称作为字符串传递,如果我使用 TABLE(tablename) 我会收到语法错误(我在下面注释掉了该行:
declare
tablename string;
column_name string;
row_count integer;
table_schema string;
table_catalog string;
name string;
tmp_array ARRAY default ARRAY_CONSTRUCT();
res resultset default (select * from PROFILE_TABLE_LIST);
c1 cursor for res;
rs_output RESULTSET;
begin
for record in c1 do
tablename := record.TABLENAME;
column_name := record.column_name;
table_schema := record.table_schema;
table_catalog := record.table_catalog;
tmp_array := array_append(:tmp_array, OBJECT_CONSTRUCT('tmp_tables', record.TABLENAME, 'COUNT', (SELECT COUNT(column_name) FROM tablename)));
-- tmp_array := array_append(:tmp_array, OBJECT_CONSTRUCT('tmp_tables', record.TABLENAME, 'COUNT', (SELECT COUNT(column_name) FROM TABLE(tablename))));
end for;
rs_output := (select value:tmp_tables, value:COUNT from table(flatten(:tmp_array)));
return table(rs_output);
end;
我会在最后构建一个 SQL 和 运行 的块。
使用简单的 SELECT 作为模式来显示构建过程的初始化,您可以编写自己的动态 sql 来自:
WITH table_list as (
SELECT * FROM VALUES
('Table1', 'PLANTS', 'TEXT'),
('Table1', 'HEIGHT', 'FLOAT'),
('Table2', 'COLOR', 'TEXT'),
('Table2', 'SMELL', 'TEXT')
v(tablename, column_name, data_type)
), to_rows as (
SELECT
tablename
,CASE data_type
WHEN 'TEXT' THEN 'SELECT ''tablename'' as TABLENAME, ''column_name'' as COLUMN_NAME, ''data_type'' as DATA_TYPE, count(column_name) as count, MAX(LEN(column_name)) as max_length, null as max_value FROM tablename '
WHEN 'FLOAT' THEN 'SELECT ''tablename'' as TABLENAME, ''column_name'' as COLUMN_NAME, ''data_type'' as DATA_TYPE, count(column_name) as count, null as max_length, MAX(column_name) as max_value FROM tablename '
END as sql
,REPLACE(REPLACE(REPLACE(sql, 'data_type', data_type), 'column_name', column_name), 'tablename', tablename) as final_sql
FROM table_list
)
SELECT
listagg (final_sql, ' UNION ALL ') within group(order by tablename) as the_big_sql
FROM to_rows;
给出:
THE_BIG_SQL
SELECT 'Table1' as TABLENAME, 'PLANTS' as COLUMN_NAME, 'TEXT' as DATA_TYPE, count(PLANTS) as count, MAX(LEN(PLANTS)) as max_length, null as max_value FROM Table1 UNION ALL SELECT 'Table1' as TABLENAME, 'HEIGHT' as COLUMN_NAME, 'FLOAT' as DATA_TYPE, count(HEIGHT) as count, null as max_length, MAX(HEIGHT) as max_value FROM Table1 UNION ALL SELECT 'Table2' as TABLENAME, 'COLOR' as COLUMN_NAME, 'TEXT' as DATA_TYPE, count(COLOR) as count, MAX(LEN(COLOR)) as max_length, null as max_value FROM Table2 UNION ALL SELECT 'Table2' as TABLENAME, 'SMELL' as COLUMN_NAME, 'TEXT' as DATA_TYPE, count(SMELL) as count, MAX(LEN(SMELL)) as max_length, null as max_value FROM Table2
如果 运行 针对这些表:
create table table1(plants text, height float);
create table table2(color text, smell text);
insert into table1 values ('big plant', 10.1),('medium plant', 5.3),('tiny', 1.0);
insert into table2 values ('red', 'bold'), ('blue', 'weak');
给出:
TABLENAME
COLUMN_NAME
DATA_TYPE
COUNT
MAX_LENGTH
MAX_VALUE
Table1
PLANTS
TEXT
3
12
Table1
HEIGHT
FLOAT
3
10.1
Table2
COLOR
TEXT
2
4
Table2
SMELL
TEXT
2
4
但这里是为您完整编写的动态答案:
首先制作 TABLE 待完成的工作:
CREATE TABLE PROFILE_TABLE_LIST AS
SELECT * FROM VALUES
('Table1', 'PLANTS', 'TEXT'),
('Table1', 'HEIGHT', 'FLOAT'),
('Table2', 'COLOR', 'TEXT'),
('Table2', 'SMELL', 'TEXT')
v(tablename, column_name, data_type);
并使用之前创建的“真实数据表”我们可以使用:
declare
sql string;
final_sql string;
c1 cursor for (select * from PROFILE_TABLE_LIST);
res resultset;
begin
final_sql := '';
for record in c1 do
if(record.data_type = 'TEXT') THEN
sql := 'SELECT '''||record.tablename||''' as TABLENAME, '''||record.column_name||''' as COLUMN_NAME, '''||record.data_type||''' as DATA_TYPE, count('||record.column_name||') as count, MAX(LEN('||record.column_name||')) as max_length, null as max_value FROM '||record.tablename||' ';
else
sql := 'SELECT '''||record.tablename||''' as TABLENAME, '''||record.column_name||''' as COLUMN_NAME, ''data_type'' as DATA_TYPE, count('||record.column_name||') as count, null as max_length, MAX('||record.column_name||') as max_value FROM '||record.tablename||' ';
end if;
if(final_sql<>'')then
final_sql := final_sql || ' UNION ALL ';
end if;
final_sql := final_sql || sql;
end for;
res := (execute immediate :final_sql);
return table(res);
end;
给出:
TABLENAME
COLUMN_NAME
DATA_TYPE
COUNT
MAX_LENGTH
MAX_VALUE
Table1
PLANTS
TEXT
3
12
Table1
HEIGHT
data_type
3
10.1
Table2
COLOR
TEXT
2
4
Table2
SMELL
TEXT
2
4
在 Snowflake 中,我正在尝试创建一个带有 for 循环的 SQL 脚本,该脚本根据 data_type 列
将结果输出到新的 table ]我有一个名为 PROFILE_TABLE_LIST 的 table,其中的列带有 table名称和列名,以及数据类型如下所示:
TABLENAME | COLUMN_NAME | DATA_TYPE |
---|---|---|
Table1 | PLANTS | TEXT |
Table1 | HEIGHT | FLOAT |
Table2 | COLOR | TEXT |
Table2 | SMELL | TEXT |
我目前正在尝试使用游标执行 for 循环并对每一行执行查询以根据列类型分析 table 看起来像这样:
TABLENAME | COLUMN_NAME | DATA_TYPE | COUNT | MAX_LENGTH | MAX_VALUE |
---|---|---|---|---|---|
Table1 | PLANTS | TEXT | 10 | 82 | NULL |
Table1 | HEIGHT | FLOAT | 10 | NULL | 58.6 |
Table2 | COLOR | TEXT | 20 | 56 | NULL |
Table2 | SMELL | TEXT | 20 | 23 | NULL |
最终,我想 运行 不同的 select 语句以 data_type 为条件,但在这个阶段,我只关注计数。这是我的当前循环。但是,select 语句未正确执行,因为 table 名称作为字符串传递,如果我使用 TABLE(tablename) 我会收到语法错误(我在下面注释掉了该行:
declare
tablename string;
column_name string;
row_count integer;
table_schema string;
table_catalog string;
name string;
tmp_array ARRAY default ARRAY_CONSTRUCT();
res resultset default (select * from PROFILE_TABLE_LIST);
c1 cursor for res;
rs_output RESULTSET;
begin
for record in c1 do
tablename := record.TABLENAME;
column_name := record.column_name;
table_schema := record.table_schema;
table_catalog := record.table_catalog;
tmp_array := array_append(:tmp_array, OBJECT_CONSTRUCT('tmp_tables', record.TABLENAME, 'COUNT', (SELECT COUNT(column_name) FROM tablename)));
-- tmp_array := array_append(:tmp_array, OBJECT_CONSTRUCT('tmp_tables', record.TABLENAME, 'COUNT', (SELECT COUNT(column_name) FROM TABLE(tablename))));
end for;
rs_output := (select value:tmp_tables, value:COUNT from table(flatten(:tmp_array)));
return table(rs_output);
end;
我会在最后构建一个 SQL 和 运行 的块。
使用简单的 SELECT 作为模式来显示构建过程的初始化,您可以编写自己的动态 sql 来自:
WITH table_list as (
SELECT * FROM VALUES
('Table1', 'PLANTS', 'TEXT'),
('Table1', 'HEIGHT', 'FLOAT'),
('Table2', 'COLOR', 'TEXT'),
('Table2', 'SMELL', 'TEXT')
v(tablename, column_name, data_type)
), to_rows as (
SELECT
tablename
,CASE data_type
WHEN 'TEXT' THEN 'SELECT ''tablename'' as TABLENAME, ''column_name'' as COLUMN_NAME, ''data_type'' as DATA_TYPE, count(column_name) as count, MAX(LEN(column_name)) as max_length, null as max_value FROM tablename '
WHEN 'FLOAT' THEN 'SELECT ''tablename'' as TABLENAME, ''column_name'' as COLUMN_NAME, ''data_type'' as DATA_TYPE, count(column_name) as count, null as max_length, MAX(column_name) as max_value FROM tablename '
END as sql
,REPLACE(REPLACE(REPLACE(sql, 'data_type', data_type), 'column_name', column_name), 'tablename', tablename) as final_sql
FROM table_list
)
SELECT
listagg (final_sql, ' UNION ALL ') within group(order by tablename) as the_big_sql
FROM to_rows;
给出:
THE_BIG_SQL |
---|
SELECT 'Table1' as TABLENAME, 'PLANTS' as COLUMN_NAME, 'TEXT' as DATA_TYPE, count(PLANTS) as count, MAX(LEN(PLANTS)) as max_length, null as max_value FROM Table1 UNION ALL SELECT 'Table1' as TABLENAME, 'HEIGHT' as COLUMN_NAME, 'FLOAT' as DATA_TYPE, count(HEIGHT) as count, null as max_length, MAX(HEIGHT) as max_value FROM Table1 UNION ALL SELECT 'Table2' as TABLENAME, 'COLOR' as COLUMN_NAME, 'TEXT' as DATA_TYPE, count(COLOR) as count, MAX(LEN(COLOR)) as max_length, null as max_value FROM Table2 UNION ALL SELECT 'Table2' as TABLENAME, 'SMELL' as COLUMN_NAME, 'TEXT' as DATA_TYPE, count(SMELL) as count, MAX(LEN(SMELL)) as max_length, null as max_value FROM Table2 |
如果 运行 针对这些表:
create table table1(plants text, height float);
create table table2(color text, smell text);
insert into table1 values ('big plant', 10.1),('medium plant', 5.3),('tiny', 1.0);
insert into table2 values ('red', 'bold'), ('blue', 'weak');
给出:
TABLENAME | COLUMN_NAME | DATA_TYPE | COUNT | MAX_LENGTH | MAX_VALUE |
---|---|---|---|---|---|
Table1 | PLANTS | TEXT | 3 | 12 | |
Table1 | HEIGHT | FLOAT | 3 | 10.1 | |
Table2 | COLOR | TEXT | 2 | 4 | |
Table2 | SMELL | TEXT | 2 | 4 |
但这里是为您完整编写的动态答案:
首先制作 TABLE 待完成的工作:
CREATE TABLE PROFILE_TABLE_LIST AS
SELECT * FROM VALUES
('Table1', 'PLANTS', 'TEXT'),
('Table1', 'HEIGHT', 'FLOAT'),
('Table2', 'COLOR', 'TEXT'),
('Table2', 'SMELL', 'TEXT')
v(tablename, column_name, data_type);
并使用之前创建的“真实数据表”我们可以使用:
declare
sql string;
final_sql string;
c1 cursor for (select * from PROFILE_TABLE_LIST);
res resultset;
begin
final_sql := '';
for record in c1 do
if(record.data_type = 'TEXT') THEN
sql := 'SELECT '''||record.tablename||''' as TABLENAME, '''||record.column_name||''' as COLUMN_NAME, '''||record.data_type||''' as DATA_TYPE, count('||record.column_name||') as count, MAX(LEN('||record.column_name||')) as max_length, null as max_value FROM '||record.tablename||' ';
else
sql := 'SELECT '''||record.tablename||''' as TABLENAME, '''||record.column_name||''' as COLUMN_NAME, ''data_type'' as DATA_TYPE, count('||record.column_name||') as count, null as max_length, MAX('||record.column_name||') as max_value FROM '||record.tablename||' ';
end if;
if(final_sql<>'')then
final_sql := final_sql || ' UNION ALL ';
end if;
final_sql := final_sql || sql;
end for;
res := (execute immediate :final_sql);
return table(res);
end;
给出:
TABLENAME | COLUMN_NAME | DATA_TYPE | COUNT | MAX_LENGTH | MAX_VALUE |
---|---|---|---|---|---|
Table1 | PLANTS | TEXT | 3 | 12 | |
Table1 | HEIGHT | data_type | 3 | 10.1 | |
Table2 | COLOR | TEXT | 2 | 4 | |
Table2 | SMELL | TEXT | 2 | 4 |