【发布时间】:2023-02-09 05:39:26
【问题描述】:
Snowflake SQL UDF 在将硬编码值作为输入参数传递时工作正常,但在 SELECT 子句中通过将实际列作为输入参数传递来使用 UDF 时失败。
已在 snowflake 社区检查过这个错误,但似乎这个错误是 4 年前报告的,目前还没有解决方案。
请有人帮助提供替代解决方案来克服雪花的这个错误。
CREATE OR REPLACE FUNCTION UDF_GET_CURR_CONV_VALUES(BASE_NET_VALUE FLOAT,EX_PRICE_DATE DATE,EX_RATE_TYPE VARCHAR(20),FROM_CURR VARCHAR(10),TO_CURR VARCHAR(10))
RETURNS VARCHAR(16777216)
LANGUAGE SQL
COMMENT='This function will return Ex rate value, net value and converted net value based on the input parameter.'
AS $$
case
when FROM_CURR = TO_CURR then ('|'||BASE_NET_VALUE||'|'||BASE_NET_VALUE)
else
(select (EXCHANGE_RATE_VALUE||'|'||ACT_BASE_NET_VALUE||'|'||CONV_NET_VALUE)
from
(select
case
when ( (2 - CURRENCY.CURRENCY_DECIMAL_PLACES) < 0 ) then round((BASE_NET_VALUE / power(10, -1 * (2 - CURRENCY.CURRENCY_DECIMAL_PLACES)))/TCURF.FROM_CURRENCY_RATIO,2)
when ( (2 - CURRENCY.CURRENCY_DECIMAL_PLACES) > 0 ) then round((BASE_NET_VALUE * power(10, 1 * (2 - CURRENCY.CURRENCY_DECIMAL_PLACES)))/TCURF.FROM_CURRENCY_RATIO,2)
else round(BASE_NET_VALUE,2) end as ACT_BASE_NET_VALUE
,round((ACT_BASE_NET_VALUE * EXRATE.EXCHANGE_RATE_VALUE),2) as CONV_NET_VALUE
,EXRATE.EXCHANGE_RATE_VALUE as EXCHANGE_RATE_VALUE
from MY_SCHEMA.MY_EXCHANGE_RATES EXRATE
LEFT JOIN MY_SCHEMA.CURRENCY CURRENCY ON CURRENCY.CURRENCY_KEY = FROM_CURR AND CURRENCY.DELETED = 'N'
LEFT JOIN (select * from MY_SCHEMA.EXCHANGE_RATE_CONVERSION_FACTORS where DELETED = 'N'
QUALIFY ROW_NUMBER() OVER (PARTITION BY EXCHANGE_RATE_TYPE,FROM_CURRENCY,TO_CURRENCY,VALID_FROM ORDER BY VALID_FROM DESC) = 1) TCURF
ON TCURF.FROM_CURRENCY = FROM_CURR AND TCURF.TO_CURRENCY = TO_CURR AND TCURF.EXCHANGE_RATE_TYPE = EX_RATE_TYPE
where equal_null(FROM_CURR,EXRATE.SOURCE_CURRENCY)
and EXRATE.EXCHANGE_RATE_TYPE = EX_RATE_TYPE
and (EX_PRICE_DATE BETWEEN EXRATE.EXCHANGE_RATE_DATE AND EXRATE.VALID_TO_DATE)
and EXRATE.TARGET_CURRENCY = TO_CURR
and EXRATE.DELETED = 'N'
))
end
$$;
当我使用作为输入参数传递的样本值调用 UDF 时,上述函数有效。
select
try_to_double(split_part(my_schema.UDF_GET_CURR_CONV_VALUES(44131.26,to_date('2020-04-24'),'M','EUR','USD'),'|',1)) as EX_RATE_VALUE
,try_to_double(split_part(my_schema.UDF_GET_CURR_CONV_VALUES(44131.26,to_date('2020-04-24'),'M','EUR','USD'),'|',2)) as BASE_VALUE
,try_to_double(split_part(my_schema.UDF_GET_CURR_CONV_VALUES(44131.26,to_date('2020-04-24'),'M','EUR','USD'),'|',3)) as USD_BASE_VALUE
;
但是,当尝试通过将实际列作为输入参数传递给 select 子句时,也会出现“SQL 编译错误:无法评估不支持的子查询类型”错误。
select
TXN_NO
,try_to_double(split_part(my_schema.UDF_GET_CURR_CONV_VALUES(NET_VALUE,PRICE_DATE,RATE_TYPE,SOURCE_CURRENCY,TARGET_CURRENCY),'|',1)) as EX_RATE_VALUE
,try_to_double(split_part(my_schema.UDF_GET_CURR_CONV_VALUES(NET_VALUE,PRICE_DATE,RATE_TYPE,SOURCE_CURRENCY,TARGET_CURRENCY),'|',2)) as BASE_VALUE
,try_to_double(split_part(my_schema.UDF_GET_CURR_CONV_VALUES(NET_VALUE,PRICE_DATE,RATE_TYPE,SOURCE_CURRENCY,TARGET_CURRENCY),'|',3)) as USD_BASE_VALUE
FROM MY_SCHEMA.MY_TRANSACTION_TABLE
WHERE TXN_NO = 'ABCXYZ'
;
【问题讨论】:
-
您是否尝试过利用 CTE 而不是子查询?这通常可以让 Snowflake 以稍微不同的方式解释查询并避免该错误。
-
你的 UDF 感觉它缺少某种形式的聚合/行限制.. 其中一些像
EX_PRICE_DATE BETWEEN exrate.exchange_rate_date AND exrate.valid_to_date感觉它会得到很多行。此外,您的 ROW_NUMBER 在分区依据和排序依据中都有valid_from。 -
@MikeWalton,似乎 SQL UDF 不支持 CTE。无论如何,我可以通过将列作为输入参数传递来在函数中使用此连接并在 SELECT 子句中动态调用函数。 SimeonPilgrim,是的,我可以在 Partition 中删除 valid_from 并仅在 ORDER BY 子句中使用,使用 between 过滤的价格日期正在处理用例场景。是否有可能使用这些连接创建函数并在 SELECT 子句中即时使用它。
-
@SimeonPilgrim,在我的用例场景中
EX_PRICE_DATE BETWEEN exrate.exchange_rate_date AND exrate.valid_to_date将只返回一个匹配条目。由于给定的交易日期将介于汇率日期和有效日期之间。所以它不返回多行。我仍然在寻求任何帮助。我也在雪花中尝试使用 Python UDF,但无法在 python UDF 中执行查询。尝试了多种方法仍然无法解决这个问题。如上所述,CTE 概念在 SQL UDF 中不被接受,它似乎在雪花中。
标签: sql snowflake-cloud-data-platform user-defined-functions