是否可以在雪花中生成动态 sql 到 return 具有各种列的行
Is it possible to generate dynamic sql to return rows with various columns in snowflake
我们将各种数据存储为 value/pairs 在 JSON 列中。
所有行的对名称都不相同,并且取决于某些元数据。
有没有一种方法可以编写 SQL 语句来根据某些元数据检索其中一些值对?
类似于动态生成的东西
SELECT MyJson:FruitShape, MyJson:Fruitsize FROM MyTable WHERE ...
我知道我可以在存储过程中创建和执行动态 SQL,但是这个 SQL 仅限于返回标量值...
我们需要一个记录集。
我会为此利用 javascript UDTF。它提供与存储过程相同的功能,但具有 table 输出。
https://docs.snowflake.net/manuals/sql-reference/udf-js-table-functions.html
如果您已经准备好动态 sql,除了标量值之外,还有其他方法可以从存储过程中获取结果集。
您可以浏览 SnowFlake 文档中的一些选项和示例:
也许我在这里过度简化了事情,但你不能...参考 JSON 列吗?
不需要存储过程或 UDTF。
如果一个 object/row 没有特定的属性,它的值将为 NULL 并且可以被测试。
如果你想以非平凡的方式转换对象和数组,JavaScript 是可行的方法,但要获得简单的属性,只需在 SQL 中进行即可。
如果您想 return 不同的列(不同的名称),那是不可能的,除非 return 具有不同属性的 VARIANT 数据类型(即像您的输入)。
[编辑:davidgarrison/waldente 的动态 SQL/result_scan 组合很好,但可能仍然难以通过执行 SQL 脚本的有限方式使用外部工具,即使该脚本仅包含两个查询]
鉴于此输入:
create or replace table t as
select parse_json() my_json
from values
('{ "FruitShape":"Round", "FruitSize":55 } '),
('{ "FruitShape":"Square" } '),
('{ "FruitShape":"Oblong", "FruitSize":22, "FruitColor":"Chartreuse" } ')
;
此查询将生成动态 SQL:
select 'select '
|| (select listagg(distinct 'my_json:'||key::text, ',') from t, lateral flatten(input=>t.my_json, mode=>'OBJECT'))
|| ' from t;';
生成了 SQL 并且输出:
select my_json:FruitShape, my_json:FruitSize, my_json:FruitColor from t;
MY_JSON:FRUITSHAPE | MY_JSON:FRUITSIZE | MY_JSON:FRUITCOLOR
-------------------+-------------------+-------------------
"Round" | 55 | NULL
"Square" | NULL | NULL
"Oblong" | 22 | "Chartreuse"
此存储过程将执行动态 SQL 而无需剪切和粘贴:
create or replace procedure p()
returns string
language javascript
strict
execute as caller
as
$$
const statement1 = `
select 'select '
|| (select listagg(distinct 'my_json:'||key::text, ', ') from t, lateral flatten(input=>t.my_json, mode=>'OBJECT'))
|| ' from t'
`
const rs1 = snowflake.execute ({sqlText: statement1})
rs1.next()
const statement2 = rs1.getColumnValue(1)
const rs2 = snowflake.execute ({sqlText: statement2})
return 'SUCCESS'
$$
;
然后就可以调用存储过程并收集结果了:
call p();
select * from table(result_scan(-2))
您提到根据某些元数据限制输出。您可以在动态 SQL 中执行此操作,例如通过过滤不同的字段列表。
感谢 davidgarrison 的 result_scan() 技巧!
希望对您有所帮助。
我们将各种数据存储为 value/pairs 在 JSON 列中。 所有行的对名称都不相同,并且取决于某些元数据。
有没有一种方法可以编写 SQL 语句来根据某些元数据检索其中一些值对?
类似于动态生成的东西
SELECT MyJson:FruitShape, MyJson:Fruitsize FROM MyTable WHERE ...
我知道我可以在存储过程中创建和执行动态 SQL,但是这个 SQL 仅限于返回标量值... 我们需要一个记录集。
我会为此利用 javascript UDTF。它提供与存储过程相同的功能,但具有 table 输出。
https://docs.snowflake.net/manuals/sql-reference/udf-js-table-functions.html
如果您已经准备好动态 sql,除了标量值之外,还有其他方法可以从存储过程中获取结果集。
您可以浏览 SnowFlake 文档中的一些选项和示例:
也许我在这里过度简化了事情,但你不能...参考 JSON 列吗?
不需要存储过程或 UDTF。
如果一个 object/row 没有特定的属性,它的值将为 NULL 并且可以被测试。
如果你想以非平凡的方式转换对象和数组,JavaScript 是可行的方法,但要获得简单的属性,只需在 SQL 中进行即可。
如果您想 return 不同的列(不同的名称),那是不可能的,除非 return 具有不同属性的 VARIANT 数据类型(即像您的输入)。
[编辑:davidgarrison/waldente 的动态 SQL/result_scan 组合很好,但可能仍然难以通过执行 SQL 脚本的有限方式使用外部工具,即使该脚本仅包含两个查询]
鉴于此输入:
create or replace table t as
select parse_json() my_json
from values
('{ "FruitShape":"Round", "FruitSize":55 } '),
('{ "FruitShape":"Square" } '),
('{ "FruitShape":"Oblong", "FruitSize":22, "FruitColor":"Chartreuse" } ')
;
此查询将生成动态 SQL:
select 'select '
|| (select listagg(distinct 'my_json:'||key::text, ',') from t, lateral flatten(input=>t.my_json, mode=>'OBJECT'))
|| ' from t;';
生成了 SQL 并且输出:
select my_json:FruitShape, my_json:FruitSize, my_json:FruitColor from t;
MY_JSON:FRUITSHAPE | MY_JSON:FRUITSIZE | MY_JSON:FRUITCOLOR
-------------------+-------------------+-------------------
"Round" | 55 | NULL
"Square" | NULL | NULL
"Oblong" | 22 | "Chartreuse"
此存储过程将执行动态 SQL 而无需剪切和粘贴:
create or replace procedure p()
returns string
language javascript
strict
execute as caller
as
$$
const statement1 = `
select 'select '
|| (select listagg(distinct 'my_json:'||key::text, ', ') from t, lateral flatten(input=>t.my_json, mode=>'OBJECT'))
|| ' from t'
`
const rs1 = snowflake.execute ({sqlText: statement1})
rs1.next()
const statement2 = rs1.getColumnValue(1)
const rs2 = snowflake.execute ({sqlText: statement2})
return 'SUCCESS'
$$
;
然后就可以调用存储过程并收集结果了:
call p();
select * from table(result_scan(-2))
您提到根据某些元数据限制输出。您可以在动态 SQL 中执行此操作,例如通过过滤不同的字段列表。
感谢 davidgarrison 的 result_scan() 技巧!
希望对您有所帮助。