如何在 Snowflake 存储过程中获取按 "ORDINAL_POSITION" 排序的结果?
How to get the result sorted by "ORDINAL_POSITION" in Snowflake stored procedure?
我已经编写了一个 Snowflake 存储过程来创建用于查看的 DDL。我使用在存储过程中编写的两个查询获取所有列,这些查询对“文本”和“日期”数据类型执行了操作。第一个查询是“文本”,第二个查询是“日期”数据类型。第二个查询在第一次执行时给出动态 SQL ,必须再次循环以获取列名。最后,附加查询结果(即来自两个查询的列名)并生成视图脚本。
CREATE OR REPLACE PROCEDURE ADMIN.generateScript (TABLENAME varchar, TABLESCHEMA varchar)
RETURNS varchar
LANGUAGE JAVASCRIPT
AS
$$
var database
database = snowflake.execute( {sqlText: "select CURRENT_DATABASE();"} );
database.next()
database_value = database.getColumnValue(1);
var TABLENAME_local = TABLENAME ;
var TABLESCHEMA_local = TABLESCHEMA ;
var column_count = 0
var newschema
//Create a query by accumulating the strings and execute the query for text columns
var q1= " select CASE WHEN DATA_TYPE = 'TEXT' THEN ',nullif('||COLUMN_NAME||','''''''') AS ' ||COLUMNS.COLUMN_NAME WHEN DATA_TYPE != 'TEXT' THEN ','||COLUMN_NAME"
q1 += " ELSE ','||COLUMN_NAME END AS ALIAS, ORDINAL_POSITION from "+ database_value +".INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = '"
q1 += TABLENAME_local
q1 += "' and TABLE_SCHEMA = '"
q1 += TABLESCHEMA_local
q1 += "' and COLUMN_NAME not like '%_SDC_%' and DATA_TYPE not in ('TIMESTAMP_TZ','TIMESTAMP_NTZ','TIMESTAMP_LTZ', 'DATE') order by ORDINAL_POSITION;"
var rs = snowflake.execute( {sqlText: q1} );
var return_value = "";
while (rs.next()) {
column_count += 1;
return_value += rs.getColumnValue(1);
}
//Create another query by accumulating the strings and execution of this query gives dynamic SQL as result for date datatype columns
var q2 = " select COLUMN_NAME,'select '''||COLUMN_NAME||''',CASE WHEN (select count(distinct cast('||COLUMN_NAME||' AS TIME)) from "+ database_value +".'||TABLE_SCHEMA||'.'||TABLE_NAME||')>1 THEN '',convert_timezone(''''''''UTC'''''''','||COLUMN_NAME||') AS '||COLUMN_NAME||''' ELSE '','||COLUMN_NAME||'::DATE AS '||COLUMN_NAME||''' END AS STATEMENT ' "
q2 += " ,ORDINAL_POSITION from "+ database_value +".INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = '"
q2 += TABLENAME_local
q2 += "' and TABLE_SCHEMA = '"
q2 += TABLESCHEMA_local
q2 += "' and COLUMN_NAME not like '%_SDC_%' and DATA_TYPE in ('TIMESTAMP_TZ','TIMESTAMP_NTZ','TIMESTAMP_LTZ', 'DATE') order by ORDINAL_POSITION;"
var rs1 = snowflake.execute( {sqlText: q2} );
var rs2
while (rs1.next()) {
rs2 = snowflake.execute( {sqlText: rs1.getColumnValue(2)} );
//Looping through the dynamic SQL output to get the actual columns
while (rs2.next()) {
column_count += 1;
return_value += rs2.getColumnValue(2);
}
}
//Remove the first comma in the first column
rs1 = snowflake.execute( {sqlText: "select RIGHT( '" + return_value + "',LEN('" + return_value + "')-1);"} );
rs1.next()
return_value = rs1.getColumnValue(1);
//Creating view
newschema = snowflake.execute( {sqlText: "select SUBSTRING('"+TABLESCHEMA_local+"',0,CHARINDEX('_','"+TABLESCHEMA_local+"')-1);"} );
newschema.next()
newschema_value = newschema.getColumnValue(1);
query_statement = "CREATE OR REPLACE view "+newschema_value+".vw_" +TABLENAME_local+" AS SELECT " + return_value + " from " + TABLESCHEMA_local + "."+ TABLENAME_local + " --WHERE ISDELETED = FALSE" ;
return query_statement;
$$;
CALL ADMIN.generateScript('Table_ABC','SCHEMA_RAW')
但是生成的视图脚本没有基于 ORDINAL_POSITION 的列名,此代码首先附加第一个查询“文本”列,然后附加第二个查询“日期”列。我想生成包含基于 ORDINAL_POSITION 的列的脚本,它可以是文本和日期数据类型的组合,如下视图:
CREATE OR REPLACE view Test_View AS
SELECT nullif(xyz,'') AS XYZ,
convert_timezone('UTC',CREATEDDATE) AS CREATEDDATE,
nullif(abc,'') AS ABC,
MODIFIED_DATE::DATE AS MODIFIED_DATE
from TABLESCHEMA.TABLENAME;
TIA
最直接、最简单的答案是,为了让您的 ORDER BY
正常工作,您需要在订购前将您的记录合并在一起。
本质上:
SELECT column
(
select num_column as column, ORDINAL_POSITION
from table
union
select date_column as column, ORDINAL_POSITION
from table
)
order by ORDINAL_POSITION
不太简单的答案是我建议从您的两个查询中提取您的基本列信息,然后使用 Javascript 到 assemble 将其放入视图定义并进行排序。这将使您免于在 Javascript.
内的 SQL 内编写 SQL
从“如何删除 Javascript 中的前导逗号”到“如何对 Javascript 中包含多列的数组进行排序”,所有内容都有一个 Whosebug。这需要一些努力,但它绝对可以简化您的代码,并且值得学习如何在 Snowflake 过程中利用 Javascript 的强大功能。
额外提示: 如果您使用 template literals 它可以显着清理您的代码并通过避免 q1 += "
语法使其更易读。
我已经编写了一个 Snowflake 存储过程来创建用于查看的 DDL。我使用在存储过程中编写的两个查询获取所有列,这些查询对“文本”和“日期”数据类型执行了操作。第一个查询是“文本”,第二个查询是“日期”数据类型。第二个查询在第一次执行时给出动态 SQL ,必须再次循环以获取列名。最后,附加查询结果(即来自两个查询的列名)并生成视图脚本。
CREATE OR REPLACE PROCEDURE ADMIN.generateScript (TABLENAME varchar, TABLESCHEMA varchar)
RETURNS varchar
LANGUAGE JAVASCRIPT
AS
$$
var database
database = snowflake.execute( {sqlText: "select CURRENT_DATABASE();"} );
database.next()
database_value = database.getColumnValue(1);
var TABLENAME_local = TABLENAME ;
var TABLESCHEMA_local = TABLESCHEMA ;
var column_count = 0
var newschema
//Create a query by accumulating the strings and execute the query for text columns
var q1= " select CASE WHEN DATA_TYPE = 'TEXT' THEN ',nullif('||COLUMN_NAME||','''''''') AS ' ||COLUMNS.COLUMN_NAME WHEN DATA_TYPE != 'TEXT' THEN ','||COLUMN_NAME"
q1 += " ELSE ','||COLUMN_NAME END AS ALIAS, ORDINAL_POSITION from "+ database_value +".INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = '"
q1 += TABLENAME_local
q1 += "' and TABLE_SCHEMA = '"
q1 += TABLESCHEMA_local
q1 += "' and COLUMN_NAME not like '%_SDC_%' and DATA_TYPE not in ('TIMESTAMP_TZ','TIMESTAMP_NTZ','TIMESTAMP_LTZ', 'DATE') order by ORDINAL_POSITION;"
var rs = snowflake.execute( {sqlText: q1} );
var return_value = "";
while (rs.next()) {
column_count += 1;
return_value += rs.getColumnValue(1);
}
//Create another query by accumulating the strings and execution of this query gives dynamic SQL as result for date datatype columns
var q2 = " select COLUMN_NAME,'select '''||COLUMN_NAME||''',CASE WHEN (select count(distinct cast('||COLUMN_NAME||' AS TIME)) from "+ database_value +".'||TABLE_SCHEMA||'.'||TABLE_NAME||')>1 THEN '',convert_timezone(''''''''UTC'''''''','||COLUMN_NAME||') AS '||COLUMN_NAME||''' ELSE '','||COLUMN_NAME||'::DATE AS '||COLUMN_NAME||''' END AS STATEMENT ' "
q2 += " ,ORDINAL_POSITION from "+ database_value +".INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = '"
q2 += TABLENAME_local
q2 += "' and TABLE_SCHEMA = '"
q2 += TABLESCHEMA_local
q2 += "' and COLUMN_NAME not like '%_SDC_%' and DATA_TYPE in ('TIMESTAMP_TZ','TIMESTAMP_NTZ','TIMESTAMP_LTZ', 'DATE') order by ORDINAL_POSITION;"
var rs1 = snowflake.execute( {sqlText: q2} );
var rs2
while (rs1.next()) {
rs2 = snowflake.execute( {sqlText: rs1.getColumnValue(2)} );
//Looping through the dynamic SQL output to get the actual columns
while (rs2.next()) {
column_count += 1;
return_value += rs2.getColumnValue(2);
}
}
//Remove the first comma in the first column
rs1 = snowflake.execute( {sqlText: "select RIGHT( '" + return_value + "',LEN('" + return_value + "')-1);"} );
rs1.next()
return_value = rs1.getColumnValue(1);
//Creating view
newschema = snowflake.execute( {sqlText: "select SUBSTRING('"+TABLESCHEMA_local+"',0,CHARINDEX('_','"+TABLESCHEMA_local+"')-1);"} );
newschema.next()
newschema_value = newschema.getColumnValue(1);
query_statement = "CREATE OR REPLACE view "+newschema_value+".vw_" +TABLENAME_local+" AS SELECT " + return_value + " from " + TABLESCHEMA_local + "."+ TABLENAME_local + " --WHERE ISDELETED = FALSE" ;
return query_statement;
$$;
CALL ADMIN.generateScript('Table_ABC','SCHEMA_RAW')
但是生成的视图脚本没有基于 ORDINAL_POSITION 的列名,此代码首先附加第一个查询“文本”列,然后附加第二个查询“日期”列。我想生成包含基于 ORDINAL_POSITION 的列的脚本,它可以是文本和日期数据类型的组合,如下视图:
CREATE OR REPLACE view Test_View AS
SELECT nullif(xyz,'') AS XYZ,
convert_timezone('UTC',CREATEDDATE) AS CREATEDDATE,
nullif(abc,'') AS ABC,
MODIFIED_DATE::DATE AS MODIFIED_DATE
from TABLESCHEMA.TABLENAME;
TIA
最直接、最简单的答案是,为了让您的 ORDER BY
正常工作,您需要在订购前将您的记录合并在一起。
本质上:
SELECT column
(
select num_column as column, ORDINAL_POSITION
from table
union
select date_column as column, ORDINAL_POSITION
from table
)
order by ORDINAL_POSITION
不太简单的答案是我建议从您的两个查询中提取您的基本列信息,然后使用 Javascript 到 assemble 将其放入视图定义并进行排序。这将使您免于在 Javascript.
内的 SQL 内编写 SQL从“如何删除 Javascript 中的前导逗号”到“如何对 Javascript 中包含多列的数组进行排序”,所有内容都有一个 Whosebug。这需要一些努力,但它绝对可以简化您的代码,并且值得学习如何在 Snowflake 过程中利用 Javascript 的强大功能。
额外提示: 如果您使用 template literals 它可以显着清理您的代码并通过避免 q1 += "
语法使其更易读。