Ошибка UDTF - SQL Ошибка компиляции: неподдерживаемый тип подзапроса не может быть оценен - PullRequest
0 голосов
/ 31 марта 2020

Я создал пользовательскую табличную функцию, которая переводит номера деталей для нашей компании. Номера деталей - это строки 15-19 di git alphanumeri c, которые дают нам различную информацию о каждом продукте. Общим сравнением будет номер автомобильного VIN. Единственное ключевое отличие состоит в том, что за эти годы структура этих чисел изменилась. Итак, один год цвет может быть символами 11 и 12, а следующий - 15 и 16. Кроме того, коды могут иметь разные значения для разных лет. Например, код «BL» может быть синим в течение одного года, а следующий - голубым. Это не идеально, но это рука, с которой мне раздали. Чтобы декодировать номера деталей, я создал пользовательскую табличную функцию. Логика c для этого изначально существовала в MS SQL. Он имеет процедурный лог c, но это не разрешено в UDTF в Snowflake. Итак, я проявил творческий подход и переписал функцию, используя CTE. Это сложно, потому что у меня есть одна таблица, которая идентифицирует структуру номера детали, и другая таблица, которая может соответствовать кодам, чтобы получить описание соответствия, основанное на любых зависимостях.

UDTF успешно запускается, когда я жестко кодирую значение: SELECT * FROM TABLE(fDecodeSmartNumber('A19GELEXXXXGRGG'));

Он также запускается успешно, если я присоединяю его к таблице, но значения не возвращаются:

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'

$$
;

Есть идеи?

1 Ответ

0 голосов
/ 31 марта 2020

Вы присоединяетесь к табличной функции, которая, вероятно, должна быть пользовательской функцией, а не UDTF, поскольку вы должны получить только одно декодирование на VIN.

Но в любом случае функция превращается в коррелированный подзапрос, который не поддерживает Snowflake, поэтому появляется сообщение об ошибке.

...