使用Postgres 9.5我已经建立了这个功能:
CREATE or REPLACE FUNCTION func_getratio_laglag(_numeratorLAG text, _n1 int, _denominatorLAG text, _n2 int, _table text)
RETURNS TABLE (date_t timestamp without time zone, customer_code text, index text, ratio real) AS
$BODY$
BEGIN
RETURN QUERY EXECUTE
'SELECT
date_t,
customer_code,
index,
(LAG('||quote_ident(_numeratorLAG)||',' || quote_literal(_n1)||') OVER W / LAG('||quote_ident(_denominatorLAG)||','|| quote_literal(_n2)||') OVER W) '
|| ' FROM ' || quote_ident(_table)
|| ' WINDOW W AS (PARTITION BY customer_code ORDER BY date_t asc);';
END;
$BODY$ LANGUAGE plpgsql;
所有功能都允许我从指定的表中选择2个不同的列,并根据不同的滞后窗口计算它们之间的比率。要执行上面的功能,我使用以下查询:
SELECT * FROM func_getratio_laglag('order_first',1,'order_last',0,'customers_hist');
这将返回一个包含列标签date_t
,customer_code
,index
和ratio
的表格。我真的很挣扎如何将比率作为动态列标签。也就是说,我希望它取决于输入参数,例如:如果我运行上面的选择查询,那么我希望列标签date_t
,customer_code
,index
和 order_first_1_order_last_0
。
我被困,有任何建议或提示吗?
答案 0 :(得分:1)
如何从输入参数到函数派生返回类型的列名?
答案简短:不可能。
SQL对列数据类型和名称非常严格。这些必须在最迟之前或在通话时间宣布。没有例外。没有真正动态的列名。
我可以想到3个中途解决方法:
按原样使用您的函数(或者更确切地说,我在下面建议的审核版本)并在函数调用中添加列别名:
SELECT * FROM func_getratio_laglag('order_first',1,'order_last',0,'customers_hist')
AS f(date_t, customer_code, index, order_first_1_order_last_0)
我会这样做。
创建函数以返回匿名记录:
RETURNS SETOF record
然后,您必须为每次调用提供列定义列表:
SELECT * FROM func_getratio_laglag('order_first',1,'order_last',0,'customers_hist')
AS f(date_t timestamp, customer_code text, index text, order_first_1_order_last_0 real)
我会 不 这样做。
如果碰巧有行类型,那么非常有用。您可以通过装箱临时表来 动态注册行类型,但这似乎 用例
。本回答最后一章的详细信息:
使用format()
使构建查询字符串更加安全和简单
Read the manual if you are not familiar with it
CREATE OR REPLACE FUNCTION func_getratio_laglag(
_numerator_lag text, _n1 int
, _denominator_lag text, _n2 int
, _table regclass)
RETURNS TABLE (date_t timestamp, customer_code text, index text, ratio real) AS
$func$
BEGIN
RETURN QUERY EXECUTE format (
'SELECT date_t, customer_code, index
, (lag(%I, %s) OVER w / lag(%I, %s) OVER w) -- data type must match
FROM %s
WINDOW w AS (PARTITION BY customer_code ORDER BY date_t)'
, _numerator_lag, _n1, _denominator_lag, _n2, _table::text
);
END
$func$ LANGUAGE plpgsql;
请注意表名的数据类型regclass
。这是我的个人(可选)建议。
除此之外:我还建议不要在Postgres中使用混合大小写标识符。