如何在雪花中以动态值为中心
Posted
技术标签:
【中文标题】如何在雪花中以动态值为中心【英文标题】:How to pivot on dynamic values in Snowflake 【发布时间】:2019-07-23 21:35:35 【问题描述】:我想根据可以包含“动态”值(并不总是事先知道)的字段来透视表。
我可以通过对值进行硬编码来使其工作(这是不可取的):
SELECT *
FROM my_table
pivot(SUM(amount) FOR type_id IN (1,2,3,4,5,20,50,83,141,...));
但我无法使用查询来动态提供值:
SELECT *
FROM my_table
pivot(SUM(amount) FOR type_id IN (SELECT id FROM types));
---
090150 (22000): Single-row subquery returns more than one row.
SELECT *
FROM my_table
pivot(SUM(amount) FOR type_id IN (SELECT ARRAY_AGG(id) FROM types));
---
001038 (22023): SQL compilation error:
Can not convert parameter 'my_table.type_id' of type [NUMBER(38,0)] into expected type [ARRAY]
有没有办法做到这一点?
【问题讨论】:
【参考方案1】:我认为这在本机 SQL 中是不可能的,但我写了 an article 并发布了一些代码,展示了我的团队如何通过从 Python 生成查询来做到这一点。
您可以直接调用 Python 脚本,传递类似于 Excel 为数据透视表提供的选项的参数:
python generate_pivot_query.py \
--dbtype snowflake --database mydb \
--host myhost.url --port 5432 \
--user me --password myp4ssw0rd \
--base-columns customer_id \
--pivot-columns category \
--exclude-columns order_id \
--aggfunction-mappings amount=sum \
myschema orders
或者,如果您是 Airflow,则可以使用 CreatePivotTableOperator
直接创建任务。
【讨论】:
【参考方案2】:我写了一个 Snowflake 存储过程来获取 Snowflake 内部的动态枢轴,检查:
https://hoffa.medium.com/dynamic-pivots-in-sql-with-snowflake-c763933987c三个步骤:
-
查询
调用存储过程
call pivot_prev_results()
查找结果select * from table(result_scan(last_query_id(-2)))
程序:
create or replace procedure pivot_prev_results()
returns string
language javascript
execute as caller as
$$
var cols_query = `
select '\\''
|| listagg(distinct pivot_column, '\\',\\'') within group (order by pivot_column)
|| '\\''
from table(result_scan(last_query_id(-1)))
`;
var stmt1 = snowflake.createStatement(sqlText: cols_query);
var results1 = stmt1.execute();
results1.next();
var col_list = results1.getColumnValue(1);
pivot_query = `
select *
from (select * from table(result_scan(last_query_id(-2))))
pivot(max(pivot_value) for pivot_column in ($col_list))
`
var stmt2 = snowflake.createStatement(sqlText: pivot_query);
stmt2.execute();
return `select * from table(result_scan('$stmt2.getQueryId()'));\n select * from table(result_scan(last_query_id(-2)));`;
$$;
【讨论】:
以上是关于如何在雪花中以动态值为中心的主要内容,如果未能解决你的问题,请参考以下文章