如何在雪花中以动态值为中心

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)));`;
$$;

【讨论】:

以上是关于如何在雪花中以动态值为中心的主要内容,如果未能解决你的问题,请参考以下文章

如何在引导程序中以表单为中心输入?

如何验证雪花时间旅行设置?

Nacos配置中心原理

如何在 JSF 2 中以编程方式或动态创建复合组件

在雪花中创建具有动态日期范围的日历表

阿里巴巴 Nacos 分布式配置中心原理