将列名作为参数传递给 Redshift 中的“PREPARE”的问题

Posted

技术标签:

【中文标题】将列名作为参数传递给 Redshift 中的“PREPARE”的问题【英文标题】:Issue with passing column name as a parameter to "PREPARE" in Redshift 【发布时间】:2019-05-07 19:55:15 【问题描述】:

我正在为以下问题使用 REDSHIFT,这是问题,我正在寻找解决方案。

我有 2 个表,一个表包含列组合,第二个表应根据这些组合对结果进行分组。

包含列组合的表 1(这是存储过程的输出):

COMBINATIONS

fruit_combinations 
  banana,'ALL'  
  banana, orange

包含fruit_baskets的表2:

FRUIT_BASKET

BANANA ORANGE USER_COUNT 
  b1     o1      5
  b1     o2      10

结果集:

FRUIT_BASKET_AGG

BANANA   ORANGE    USER_COUNT 
  b1     'ALL'       15
  b1      o1         5
  b1      o2         10

在 Redshift 中尝试过的解决方案:

PREPARE executesql(VARCHAR(10),VARCHAR(10))
AS 
select $1,$2, sum(fb.user_Count) as user_count
from dv_product.fruit_basket fb
group by 1,2;

EXECUTE executesql("BANANA","ORANGE") ;
DEALLOCATE executesql;

Error: [Amazon](500310) Invalid operation: column "banana" does not exist;

问题:

1 - 有没有办法可以将列名作为参数传递给 sql 语句并执行 sql?

2 - 在 Redshift 中实现上述结果集的其他替代方法是什么?

【问题讨论】:

作为参数?不,您不能将标识符作为参数传递,您需要动态 SQL 来执行此操作。 谢谢萨米。 Redshift 不支持动态 sql。除了“PREPARE”还有其他方法可以得到结果集吗? 不,抱歉,我不知道 Redshift。 Redshift: Executing a dynamic query from a string的可能重复 新的Overview of Stored Procedures in Amazon Redshift - Amazon Redshift 功能可能会有所帮助,但我怀疑它会有相同的限制。 【参考方案1】:

现在可以使用存储过程完成,而无需PREPARE。 "Overview of Stored Procedures in Amazon Redshift"

您似乎正在尝试模拟 GROUPING SETSROLLUP 功能。我在动态 SQL 中添加了UNION ALL 来提供这种类型的输出。

对于此示例存储过程,两个列名都作为输入提供,REFCURSOR 声明为输出。

CREATE PROCEDURE get_fruit_sum(IN column_1 VARCHAR, IN column_2 VARCHAR, result_set INOUT REFCURSOR) AS $$
BEGIN
OPEN result_set FOR
EXECUTE 'SELECT '|| quote_ident(column_1) ||' , '|| quote_ident(column_2) 
        || ' , SUM(fb.user_Count) as user_count ' 
        || 'FROM dv_product.fruit_basket fb GROUP BY 1,2'
        || 'UNION ALL '
        || 'SELECT '|| quote_ident(column_1) ||' , ''ALL'''
        || ' , SUM(fb.user_Count) as user_count ' 
        || 'FROM dv_product.fruit_basket fb GROUP BY 1;'  
RETURN;
END;
$$ LANGUAGE plpgsql;

您在调用过程时指定列和输出 REFCURSOR。如果需要,可以通过另一个存储过程从表中检索列名。然后从 REFCURSOR 获取输出。

BEGIN; 
CALL get_fruit_sum ( 'Banana','Orange','result_set' ); 
FETCH ALL FROM result_set; 
END;

【讨论】:

谢谢乔。这很有帮助。游标在庞大的结果集上表现如何? 对于数百行到数千行 REFCURSOR 很好。对于数百万行,我建议将结果发送到临时表。 docs.aws.amazon.com/redshift/latest/dg/…

以上是关于将列名作为参数传递给 Redshift 中的“PREPARE”的问题的主要内容,如果未能解决你的问题,请参考以下文章

是否可以将可变数量的参数传递给redshift中的存储过程?

将 BLOB/CLOB 作为参数传递给 PL/SQL 函数

Spring Data JPA - 将列名和值作为参数传递

将数组中的所有值作为参数传递给函数

将实例变量作为参数传递给同一类中的方法?

将数组作为参数传递给 C 中的函数