【问题标题】:Snowflake Stored Procedure Dynamic Column Pivot雪花存储过程动态列枢轴
【发布时间】:2021-05-12 19:26:48
【问题描述】:

我正在尝试在 Snowflake 中创建一个存储过程,以透视派生表中的数据。枢轴列本质上是动态的。我找到了一种通过参数传递来做到这一点的方法。我试图在不传递任何参数的情况下做同样的事情,但代码不起作用。

我的方法是在表中应用一个循环,我从中将列提取到一个变量中。然后在枢轴中传递这个变量。 while 循环本身似乎工作正常。将此变量传递给枢轴时出现错误。

我正在使用的代码:

CREATE OR REPLACE PROCEDURE LOOP_EXMPL_5()
returns  varchar
language javascript
as
$$ 
var column1 = 'qwerty';
var command = `SELECT ATTR_NAME FROM TBL_DIM`;
var stmt = snowflake.createStatement({sqlText: command});
var rs = stmt.execute();
while (rs.next()) 
   {
     var column1 = column1.concat(",","'",rs.getColumnValue(1),"'"); 
   }
var column2 = column1
var command_1 = `CREATE OR REPLACE VIEW HIERARCHY_VIEW_2 AS SELECT * FROM (SELECT MSTR.PROD_CODE AS 
PROD_CODE,DIM.ATTR_NAME AS ATTR_NAME,MSTR.ATTR_VALUE AS ATTR_VALUE FROM TBL_DIM DIM INNER JOIN 
TBL_MSTR MSTR ON DIM.ATTR_KEY=MSTR.ATTR_KEY ) Q
              PIVOT (MAX (Q.ATTR_VALUE) FOR Q.ATTR_NAME IN ('${column2}'))
              AS P
              ORDER BY P.PROD_CODE;`;
 var stmt_1 = snowflake.createStatement({sqlText: command_1});
 var rs_1 = stmt_1.execute();
 return 'success'
 $$;   

我得到的错误:

存储过程 LOOP_EXMPL_5 中的执行错误:SQL 编译错误:第 2 行位置 73 的语法错误意外“区域”。在 Statement.execute 第 16 行位置 21。

正在传递的变量值:

qwerty,'Region','Sub-Region','Division','Company-Product','Company-Mfg','Company-Ship From to Customer','Business Unit','Category','子品类','细分','子细分','品牌','综合品牌','子品牌','PPG'

我会以某种方式删除 SQL 中的 qwerty 部分。

【问题讨论】:

标签: stored-procedures snowflake-cloud-data-platform


【解决方案1】:

这是工作代码。非常感谢 Felipe 和 Greg 的帮助。

CREATE OR REPLACE PROCEDURE LOOP_EXMPL_9()
returns  varchar
language javascript
as
$$ 
  var column1 = "";
  var command = `SELECT ATTR_NAME FROM TBL_DIM`;
  var stmt = snowflake.createStatement({sqlText: command});
  var rs = stmt.execute();
  while (rs.next()) 
   {
     if (column1 != "") column1 += ",";
     column1 += `'${rs.getColumnValue (1)}'`;
   }
  var column2 = column1;
  var command_1 = `CREATE OR REPLACE VIEW HIERARCHY_VIEW_2 AS SELECT * FROM (SELECT 
  MSTR.PROD_CODE AS PROD_CODE,DIM.ATTR_NAME AS ATTR_NAME,MSTR.ATTR_VALUE AS ATTR_VALUE 
  FROM TBL_DIM DIM INNER JOIN TBL_MSTR MSTR ON DIM.ATTR_KEY=MSTR.ATTR_KEY ) Q
              PIVOT (MAX (Q.ATTR_VALUE) FOR Q.ATTR_NAME IN (${column2}))
              AS P
              ORDER BY P.PROD_CODE;`;
  var stmt_1 = snowflake.createStatement({sqlText: command_1});
  var rs_1 = stmt_1.execute();
  return 'success'   
$$;   

【讨论】:

    【解决方案2】:

    你可以从一个空字符串开始:

    var column1 = "";
    

    然后您可以像这样连接列列表:

    if (column1 != "") column1 += ",";
    column1 += `"${rs.getColumnValue(1)}"`);
    

    您收到 SQL 语法错误的原因是列名在应该用双引号括起来时用单引号括起来。

    【讨论】:

    • 谢谢格雷格。我试过用双引号。得到以下错误。存储过程 LOOP_EXMPL_9 中的执行错误:SQL 编译错误:位置 63 处的语法错误第 2 行意外 ''"Region","Sub-Region","Division","Company-Product","Company-Mfg","Company-从客户发货","业务单位","类别","子类别","细分","子细分","品牌","综合品牌","子品牌","PPG"' '。在 Statement.execute 第 17 行位置 21
    • PIVOT (MAX (Q.ATTR_VALUE) FOR Q.ATTR_NAME IN '${column2}')) --> 我相信添加的单引号可能会导致问题。不过我可能错了。
    • 您可以转到查询历史选项卡并查看 SP 尝试运行的 SQL 语句。获取整个语句可以更容易地修复。如果时间不长但仍需要帮助,您可以在此处发布。
    • 搞定了!您查看历史的想法帮助我进行了调试。我将发布我正在使用的代码。
    【解决方案3】:

    有关您的目标,请参阅:

    调试当前问题:column1.concat(",","'",rs.getColumnValue(1),"'"); 没有正确转义和引用列名。

    设置 UDF 以返回该值,然后返回 var command_1 的值,以便您可以进行适当的调试。

    转义列的好方法:

    select '\\'' 
            || listagg(distinct pivot_column, '\\',\\'') within group (order by pivot_column)
            || '\\'' 
    

    然后使用:

    for pivot_column in (${col_list}))
    

    【讨论】:

    • 感谢费利佩的回答。但是,在我进行列聚合的部分中,您想知道为什么包含 \\?
    • 另外,在查看反斜杠中使用的引号时,是否有原因在开头的反斜杠后出现双引号,在枢轴 listagg 函数中,最后一个?
    • 如需进一步帮助,请粘贴函数为column2command_1 打印的值。然后我们就可以正常调试了。
    • 能够弄清楚。将在此处发布解决方案。
    • 很高兴你解决了这个问题。请投票或接受任何对您有帮助的答案,以表达对堆栈溢出的感激之情
    猜你喜欢
    • 1970-01-01
    • 2021-06-22
    • 2021-12-26
    • 1970-01-01
    • 2021-10-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-13
    • 2021-08-25
    相关资源
    最近更新 更多