雪花标量 UDF 返回 无法评估不支持的子查询类型
Posted
技术标签:
【中文标题】雪花标量 UDF 返回 无法评估不支持的子查询类型【英文标题】:Snowflake scalar UDF returns Unsupported subquery type cannot be evaluated 【发布时间】:2019-11-14 21:35:17 【问题描述】:我们正在使用 JDE 作为 SOURce 并使用 Snowflake 作为 DW 进行数据仓库工作。因此,我们需要在当前具有 JDE_Julian 日期的许多字段中使用正常日期。 目前,如果我们有 6 个日期需要在查询中转换,我们必须绑定到我们的日期维度表 6 次(Snowflake 可以很好地做到这一点),但我们正在寻找一种更简洁的解决方案,即 UDF仅返回给定 JDE_Julian_Date 的日期的函数。我们想出了这个,但收到可怕的“SQL 编译错误:无法评估不支持的子查询类型” 我在这里提出了这个问题。不幸的是,它在我看来就像一个SnowFlake Bug。但我愿意接受任何不强迫我对查找表进行 6 次联接的见解。
CREATE OR REPLACE TABLE mydd (day date, JDE_Julian INT);
INSERT INTO mydd
VALUES
('2017-01-01',117001),
('2017-01-02',117002),
('2017-01-03',117003);
CREATE OR REPLACE TABLE mySource (id INT, j1 INT);
INSERT INTO mySource
VALUES
(1,117002),
(2,117002),
(3,117003),
(4,117001);
CREATE OR REPLACE FUNCTION jdetest(julian_date_in int)
RETURNS date
VOLATILE
COMMENT = 'Convert JDE Julian date to regular Date'
AS
$$
SELECT day FROM mydd
WHERE JDE_Julian = julian_date_in
$$;
SELECT jdetest(117001); --Works
SELECT jdetest(117002); --Works
SELECT id, jdetest(j1) b1 FROM mysource; --Fails
【问题讨论】:
【参考方案1】:您的函数必须保证只返回一个值。如果您将其设为聚合或其他内容,则 Snowflake 将知道仅返回 1 个值,而不是可能的记录集。试试这个,它对我有用:
CREATE OR REPLACE FUNCTION jdetest(julian_date_in int)
RETURNS date
VOLATILE
COMMENT = 'Convert JDE Julian date to regular Date'
AS
$$
SELECT max(day) as day FROM mydd
WHERE JDE_Julian = julian_date_in
$$;
【讨论】:
这是正确的答案,IMO。另外,如果你不喜欢以这种方式使用 MAX() 的想法,你可以使用 Snowflake 的 ANY_VALUE() 函数来代替。换句话说,“...SELECT ANY_VALUE(day) as day...”。 感谢@Mike,它可以工作,但不知道为什么我们需要一个类似 max 的函数。在这里看起来像是一种非常规的方法 该函数只能返回 1 个值,因此它需要有某种聚合以确保永远只返回 1 个值。正如@DarrenGardner 上面提到的,该聚合也可能是 ANY_VALUE(),因为您实际上并没有选择返回超过 1 个值的情况。【参考方案2】:请将返回类型更改为表格类型,如下所示,它应该可以工作。
RETURNS TABLE(val date)
VOLATILE
COMMENT = 'Convert JDE Julian date to regular Date'
AS
$$
SELECT day FROM mydd
WHERE JDE_Julian = julian_date_in
$$;
SELECT s.id, f.val AS b1 FROM mysource s
JOIN TABLE(jdetest( s.j1)) f
【讨论】:
不过,它并不是真正要返回的表,因此将其设为 UDTF 会使请求过于复杂。确保单一价值回报使这更容易。以上是关于雪花标量 UDF 返回 无法评估不支持的子查询类型的主要内容,如果未能解决你的问题,请参考以下文章
SQL 编译错误:无法评估不受支持的子查询类型 - SELECT 子句中的函数调用