在 Snowflake 中,我试图通过创建一个 UDTF 来根据
v
或 x
中是否存在符合某种模式的行来显示每行 y
的标志,从而节省大量代码大小和维护成本。
我得到的错误是
SQL Error [2031] [42601]: SQL compilation error: Unsupported subquery type cannot be evaluated
这是一些最小的示例代码:
DROP TABLE IF EXISTS v;
CREATE TABLE v (CHARTGUID NUMBER(16));
INSERT INTO v VALUES(1410522400170);
INSERT INTO v VALUES(1548089000170);
DROP TABLE IF EXISTS x;
CREATE TABLE x (CHARTGUID NUMBER(16), FOO INT, BAR VARCHAR(1));
INSERT INTO x(CHARTGUID, FOO, BAR) VALUES (1410522400170, 1, 'a');
INSERT INTO x(CHARTGUID, FOO, BAR) VALUES (1548089000170, 0, 'a');
DROP TABLE IF EXISTS y;
CREATE TABLE y (CHARTGUID NUMBER(16), FOO INT, BAR VARCHAR(1));
INSERT INTO y(CHARTGUID, FOO, BAR) VALUES (1410522400170, 0, 'a');
INSERT INTO y(CHARTGUID, FOO, BAR) VALUES (1548089000170, 1, 'a');
INSERT INTO y(CHARTGUID, FOO, BAR) VALUES (1548089000170, 1, 'b');
CREATE OR REPLACE FUNCTION TEST_C(CHART_GUID NUMBER, p VARCHAR)
RETURNS TABLE(A INT, B INT)
AS
$$
SELECT
CASE WHEN EXISTS (
SELECT x.CHARTGUID
FROM x
WHERE x.CHARTGUID = CHART_GUID
AND x.FOO = 1
AND x.BAR = p
) THEN 1 ELSE 0 END,
CASE WHEN EXISTS (
SELECT y.CHARTGUID
FROM y
WHERE y.CHARTGUID = CHART_GUID
AND y.FOO = 1
AND y.BAR = p
) THEN 1 ELSE 0 END,
$$
;
SELECT
v.CHARTGUID,
x.*
FROM v,
TABLE(TEST_C(v.CHARTGUID, 'a')) x
真正的用例有很多
TABLE(TEST_C(v.CHARTGUID, 'a'))
,其中'a'
是一个正则表达式模式,需要针对每个模式检查它在两个表x
和y
中的存在。
雪花“子查询限制”的解决方法是什么?
所以表格可以用不同的方式写,我觉得更干净,因为字符更少,因此更具可读性,并且它们是原子操作:
CREATE or replace TABLE v (CHARTGUID number)
as select * from values
(1410522400170),
(1548089000170);
CREATE or replace TABLE x (CHARTGUID number, FOO number, BAR text)
as select * from values
(1410522400170, 1, 'a'),
(1548089000170, 0, 'a');
CREATE or replace TABLE y (CHARTGUID number, FOO number, BAR text)
as select * from values
(1410522400170, 0, 'a'),
(1548089000170, 1, 'a'),
(1548089000170, 1, 'b');
我倾向于预处理数据,以便它可以与 CTE 等连接基(左或正常)
WITH xx as (
select distinct chartguid
from x
where foo = 1
), yy as (
select distinct chartguid
from y
where foo = 1
)
SELECT
v.chartguid,
NVL2(xx.chartguid, 1,0) as x1,
NVL2(yy.chartguid, 1,0) as x2
FROM v
LEFT JOIN xx
on xx.chartguid = v.chartguid
LEFT JOIN yy
on yy.chartguid = v.chartguid
这不会为您提供“一个隐藏所有工作的巧妙功能”,这通常是一个粗俗的技巧,但如果您需要聪明,您可以创建一个 UDTF,在连接主表之前将这两个+ CTE 连接在一起,但这可能会做工作量太大了。