UDTF Error- SQL compilation error: Unsupported subquery type cannot be evaluated
UDTF Error- SQL compilation error: Unsupported subquery type cannot be evaluated
我创建了一个用户定义的 table 函数来为我们公司翻译部件号。部件号是 15-19 位字母数字字符串,为我们提供有关每种产品的不同信息。一个常见的比较是汽车 VIN 号码。一个关键的区别是,多年来,这些数字的结构发生了变化。因此,某一年颜色可能是字符 11 和 12,下一年可能是 15 和 16。此外,不同年份的代码可能具有不同的含义。例如,代码 "BL" 可能有一年是蓝色的,但下一年可能是浅蓝色。这并不理想,但这是我得到的一手牌。为了解码零件号,我创建了一个用户定义的 Table 函数。 MS SQL 中原来就有这个逻辑。它具有程序逻辑,但在 Snowflake 的 UDTF 中不允许这样做。因此,我发挥创意并使用 CTE 重写了函数。这很复杂,因为我有一个 table 可以识别零件号的结构,另一个 table 可以匹配代码以获得基于任何依赖项的匹配描述。
当我硬编码一个值时,UDTF 成功运行:
SELECT * FROM TABLE(fDecodeSmartNumber('A19GELEXXXXGRGG'));
如果我用 table 连接它也能成功运行,但没有返回任何值:
SELECT sr.Company, sr.RMANum, sr.OrderNumber, d.FieldValue
FROM
tRMADataFinal sr
JOIN
table(fDecodeSmartNumber(sr.PartNumber)) d
WHERE
OrderNUmber IS NOT NULL AND
WAVLine IS NULL AND
Make IS NULL AND
FieldName = 'Make' AND
FieldValue IS NOT NULL
但是,如果我向 RMA 数据添加不会被 where 子句过滤的字段,则会出错。
我很好奇这是否与此处看到的错误相同:
https://docs.snowflake.com/en/sql-reference/udf-table-functions.html
但是,我认为该解决方法对我不起作用,因为我需要在函数中左连接的 "on" 子句中使用多个连接条件。
完整功能代码:
CREATE OR REPLACE FUNCTION fDecodePartNumber
(
vPartNumber varchar
)
RETURNS TABLE
(
Code VARCHAR(25),
FieldName VARCHAR(200),
FieldValue VARCHAR(200)
)
AS
$$
with SNValues as (
SELECT
FieldName,
SUBSTRING(vPartNumber,Position,Length) as SNValue
FROM
SmartDecodeParts
WHERE
SNFormat = (SELECT CASE WHEN SUBSTRING(vPartNumber,2,2) >= 18 THEN '2018' ELSE '2017' END)
),
FirstResultSet as (
SELECT
V.SNValue as Code, V.FieldName, K.Dsc, K.Dependency, K.Dvalue
FROM
SNValues V
LEFT JOIN
SmartDecodeKeys K
ON
V.SNValue = K.Code AND
V.FieldName = K.FieldName
),
extColor as (
SELECT
N.Code,
REPLACE(N.FieldName,' ','') as FieldName,
Color,
STANDARD_COLOR,
C.Dependency,
C.DValue
FROM
FirstResultSet N
INNER JOIN
ColorTranslation C
ON
N.Code = C.SMART_CODE
INNER JOIN
FirstResultSet R
ON
R.Dsc = C.STANDARD_MAKE
WHERE
N.FieldName = 'Ext Color'
),
intColor as (
SELECT
N.Code,
Replace(N.FieldName,' ','') as FieldName,
Color,
STANDARD_COLOR,
C.Dependency,
C.DValue
FROM
FirstResultSet N
INNER JOIN
ColorTranslationInterior C
ON
N.Code = LEFT(C.SMART_CODE,(SELECT Length FROM SmartDecodeParts WHERE FieldName = 'Int Color' AND SNFormat = (SELECT CASE WHEN SUBSTRING(vPartNumber,2,2) >= 18 THEN '2018' ELSE '2017' END)))
INNER JOIN
FirstResultSet R
ON
R.Dsc = C.STANDARD_MAKE
WHERE
N.FieldName = 'Int Color'
),
seatColor as (
SELECT
N.Code,
REPLACE(N.FieldName,' ','') as FieldName,
Color,
STANDARD_COLOR,
C.Dependency,
C.DValue
FROM
FirstResultSet N
INNER JOIN
ColorTranslationSeat C
ON
N.Code = C.SMART_CODE
INNER JOIN
FirstResultSet R
ON
R.Dsc = C.STANDARD_MAKE
WHERE
N.FieldName = 'Seat Color'
),
NormalizedResult as (
SELECT * FROM FirstResultSet
UNION ALL
Select Code, FieldName, Color, Dependency, DValue FROM extColor
UNION ALL
SELECT Code, 'StdExtColor', STANDARD_COLOR, Dependency, DValue FROM extColor
UNION ALL
Select Code, FieldName, Color, Dependency, DValue FROM intColor
UNION ALL
SELECT Code, 'StdIntColor', STANDARD_COLOR, Dependency, DValue FROM intColor
UNION ALL
Select Code, FieldName, Color, Dependency, DValue FROM seatColor
UNION ALL
SELECT Code, 'StdSeatColor', STANDARD_COLOR, Dependency, DValue FROM seatColor
),
NormalizedWithDependencies as (
SELECT
Code, FieldName, Dsc, Dependency, m.value::string as DValue
FROM
NormalizedResult,
lateral flatten(input=>split(DValue, ',')) m
UNION ALL
SELECT
*
FROM
NormalizedResult
WHERE
DValue IS NULL
)
SELECT
D.Code,
REPLACE(D.FieldName,' ',''),
D.Dsc
FROM
NormalizedWithDependencies D
LEFT JOIN
NormalizedWithDependencies R
ON
CASE WHEN LEFT(D.DValue,1) = '!' AND SUBSTRING(D.DValue,2,LEN(R.DValue)-1) <> R.Code THEN 1
WHEN LEFT(D.DValue,1) <> '!' AND D.DValue = R.Code THEN 1
ELSE 0 END = 1 AND
D.Dependency = R.FieldName
LEFT JOIN
NormalizedWithDependencies R2
ON
CASE WHEN LEFT(R.DValue,1) = '!' AND SUBSTRING(R.DValue,2,LEN(R.DValue)-1) <> R2.Code THEN 1
WHEN LEFT(R.DValue,1) <> '!' AND R.DValue = R2.Code THEN 1
ELSE 0 END = 1 AND
R.Dependency = R2.FieldName
WHERE
(D.Dependency IS NULL OR
(R.Code IS NOT NULL AND R.Dependency IS NULL) OR
(R.Code IS NOT NULL AND R2.Code IS NOT NULL)) AND
D.FieldName <> 'Ext Color' AND
D.FieldName <> 'Int Color' AND
D.FieldName <> 'Seat Color'
$$
;
有什么想法吗?
您正在加入一个 table 函数,它可能应该是一个用户定义的函数而不是 UDTF,因为您应该只对每个 VIN 进行一次解码。
但无论如何该函数变成了 Snowflake 不支持的相关子查询,因此出现了错误消息。
我创建了一个用户定义的 table 函数来为我们公司翻译部件号。部件号是 15-19 位字母数字字符串,为我们提供有关每种产品的不同信息。一个常见的比较是汽车 VIN 号码。一个关键的区别是,多年来,这些数字的结构发生了变化。因此,某一年颜色可能是字符 11 和 12,下一年可能是 15 和 16。此外,不同年份的代码可能具有不同的含义。例如,代码 "BL" 可能有一年是蓝色的,但下一年可能是浅蓝色。这并不理想,但这是我得到的一手牌。为了解码零件号,我创建了一个用户定义的 Table 函数。 MS SQL 中原来就有这个逻辑。它具有程序逻辑,但在 Snowflake 的 UDTF 中不允许这样做。因此,我发挥创意并使用 CTE 重写了函数。这很复杂,因为我有一个 table 可以识别零件号的结构,另一个 table 可以匹配代码以获得基于任何依赖项的匹配描述。
当我硬编码一个值时,UDTF 成功运行:
SELECT * FROM TABLE(fDecodeSmartNumber('A19GELEXXXXGRGG'));
如果我用 table 连接它也能成功运行,但没有返回任何值:
SELECT sr.Company, sr.RMANum, sr.OrderNumber, d.FieldValue
FROM
tRMADataFinal sr
JOIN
table(fDecodeSmartNumber(sr.PartNumber)) d
WHERE
OrderNUmber IS NOT NULL AND
WAVLine IS NULL AND
Make IS NULL AND
FieldName = 'Make' AND
FieldValue IS NOT NULL
但是,如果我向 RMA 数据添加不会被 where 子句过滤的字段,则会出错。
我很好奇这是否与此处看到的错误相同: https://docs.snowflake.com/en/sql-reference/udf-table-functions.html
但是,我认为该解决方法对我不起作用,因为我需要在函数中左连接的 "on" 子句中使用多个连接条件。
完整功能代码:
CREATE OR REPLACE FUNCTION fDecodePartNumber
(
vPartNumber varchar
)
RETURNS TABLE
(
Code VARCHAR(25),
FieldName VARCHAR(200),
FieldValue VARCHAR(200)
)
AS
$$
with SNValues as (
SELECT
FieldName,
SUBSTRING(vPartNumber,Position,Length) as SNValue
FROM
SmartDecodeParts
WHERE
SNFormat = (SELECT CASE WHEN SUBSTRING(vPartNumber,2,2) >= 18 THEN '2018' ELSE '2017' END)
),
FirstResultSet as (
SELECT
V.SNValue as Code, V.FieldName, K.Dsc, K.Dependency, K.Dvalue
FROM
SNValues V
LEFT JOIN
SmartDecodeKeys K
ON
V.SNValue = K.Code AND
V.FieldName = K.FieldName
),
extColor as (
SELECT
N.Code,
REPLACE(N.FieldName,' ','') as FieldName,
Color,
STANDARD_COLOR,
C.Dependency,
C.DValue
FROM
FirstResultSet N
INNER JOIN
ColorTranslation C
ON
N.Code = C.SMART_CODE
INNER JOIN
FirstResultSet R
ON
R.Dsc = C.STANDARD_MAKE
WHERE
N.FieldName = 'Ext Color'
),
intColor as (
SELECT
N.Code,
Replace(N.FieldName,' ','') as FieldName,
Color,
STANDARD_COLOR,
C.Dependency,
C.DValue
FROM
FirstResultSet N
INNER JOIN
ColorTranslationInterior C
ON
N.Code = LEFT(C.SMART_CODE,(SELECT Length FROM SmartDecodeParts WHERE FieldName = 'Int Color' AND SNFormat = (SELECT CASE WHEN SUBSTRING(vPartNumber,2,2) >= 18 THEN '2018' ELSE '2017' END)))
INNER JOIN
FirstResultSet R
ON
R.Dsc = C.STANDARD_MAKE
WHERE
N.FieldName = 'Int Color'
),
seatColor as (
SELECT
N.Code,
REPLACE(N.FieldName,' ','') as FieldName,
Color,
STANDARD_COLOR,
C.Dependency,
C.DValue
FROM
FirstResultSet N
INNER JOIN
ColorTranslationSeat C
ON
N.Code = C.SMART_CODE
INNER JOIN
FirstResultSet R
ON
R.Dsc = C.STANDARD_MAKE
WHERE
N.FieldName = 'Seat Color'
),
NormalizedResult as (
SELECT * FROM FirstResultSet
UNION ALL
Select Code, FieldName, Color, Dependency, DValue FROM extColor
UNION ALL
SELECT Code, 'StdExtColor', STANDARD_COLOR, Dependency, DValue FROM extColor
UNION ALL
Select Code, FieldName, Color, Dependency, DValue FROM intColor
UNION ALL
SELECT Code, 'StdIntColor', STANDARD_COLOR, Dependency, DValue FROM intColor
UNION ALL
Select Code, FieldName, Color, Dependency, DValue FROM seatColor
UNION ALL
SELECT Code, 'StdSeatColor', STANDARD_COLOR, Dependency, DValue FROM seatColor
),
NormalizedWithDependencies as (
SELECT
Code, FieldName, Dsc, Dependency, m.value::string as DValue
FROM
NormalizedResult,
lateral flatten(input=>split(DValue, ',')) m
UNION ALL
SELECT
*
FROM
NormalizedResult
WHERE
DValue IS NULL
)
SELECT
D.Code,
REPLACE(D.FieldName,' ',''),
D.Dsc
FROM
NormalizedWithDependencies D
LEFT JOIN
NormalizedWithDependencies R
ON
CASE WHEN LEFT(D.DValue,1) = '!' AND SUBSTRING(D.DValue,2,LEN(R.DValue)-1) <> R.Code THEN 1
WHEN LEFT(D.DValue,1) <> '!' AND D.DValue = R.Code THEN 1
ELSE 0 END = 1 AND
D.Dependency = R.FieldName
LEFT JOIN
NormalizedWithDependencies R2
ON
CASE WHEN LEFT(R.DValue,1) = '!' AND SUBSTRING(R.DValue,2,LEN(R.DValue)-1) <> R2.Code THEN 1
WHEN LEFT(R.DValue,1) <> '!' AND R.DValue = R2.Code THEN 1
ELSE 0 END = 1 AND
R.Dependency = R2.FieldName
WHERE
(D.Dependency IS NULL OR
(R.Code IS NOT NULL AND R.Dependency IS NULL) OR
(R.Code IS NOT NULL AND R2.Code IS NOT NULL)) AND
D.FieldName <> 'Ext Color' AND
D.FieldName <> 'Int Color' AND
D.FieldName <> 'Seat Color'
$$
;
有什么想法吗?
您正在加入一个 table 函数,它可能应该是一个用户定义的函数而不是 UDTF,因为您应该只对每个 VIN 进行一次解码。
但无论如何该函数变成了 Snowflake 不支持的相关子查询,因此出现了错误消息。