Я пытаюсь создать рекурсивный запрос, основанный на условии LEFT JOIN
, но не уверен, возможно ли это, особенно в Snowflake.
У меня есть три таблицы: ITEM
, ITEMHIERARCHY
и ITEMVALUE
CREATE TABLE ITEM
(
NAME STRING
);
INSERT INTO ITEM(NAME)
VALUES
('Item1'),('Item2'),('Item3'),('Item4'),('Item5'),('Item6');
CREATE TABLE ITEMHIERARCHY
(
ITEM STRING,
SUBITEM STRING
);
INSERT INTO ITEMHIERARCHY(ITEM,SUBITEM)
VALUES
('Item2','Item3'),('Item2','Item4'),('Item4','Item5'),('Item6','Item4');
CREATE TABLE ITEMVALUE
(
ITEM STRING,
VALUE NUMERIC(25,10)
);
INSERT INTO ITEMVALUE(ITEM,VALUE)
VALUES
('Item1',34.2),('Item3',40.5),('Item5',20.3),('Item6',77.7);
Моя цель - вернуть список всех ITEMs
со свернутыми значениями и значениями подпунктов:
Item1, 34.2
Item2, 60.8 //roll-up of Item3 + Item4
Item3, 40.5
Item4, 20.3 //roll-up of Item5
Item5, 20.3
Item6, 77.7 //since Item6 value is given, dont roll-up from Item4
Обратите внимание, что несмотря на то, что Item6
- это свертка из Item4
, потому что в таблице ITEMVALUE
уже есть заданное значение 77.7
, свертка игнорируется.
Вот моя попытка неудачный рекурсивный запрос из-за LEFT JOIN
в предложении UNION ALL
:
WITH RECURSIVE ITEMHIERARCHYFULL
-- Column names for the "view"/CTE
(ITEM,SUBITEM,VALUE)
AS
-- Common Table Expression
(
-- Anchor Clause
SELECT it.NAME ITEM, ih.SUBITEM, iv.VALUE
FROM ITEM it
--These left-joins work
LEFT JOIN ITEMVALUE iv ON iv.ITEM = it.NAME
LEFT JOIN ITEMHIERARCHY ih ON ih.ITEM = it.ITEM
AND iv.VALUE IS NULL
UNION ALL
-- Recursive Clause
SELECT ihf.ITEM, ih.SUBITEM,
IFF(ihf.VALUE IS NOT NULL,ihf.VALUE,iv.VALUE)
FROM ITEMHIERARCHYFULL ihf
LEFT JOIN ITEMVALUE iv ON iv.ITEM = ihf.SUBITEM
LEFT JOIN ITEMHIERARCHY ih ON ih.ITEM = ihf.SUBITEM
AND iv.VALUE IS NULL
)
-- This is the "main select".
SELECT ITEM, SUM(VALUE) AS VALUE
FROM ITEMHIERARCHYFULL
GROUP BY ITEM
ORDER BY ITEM
;
Цель запроса - сначала получить весь верхний уровень ITEMs
из таблицы ITEM
, поиск соответствующее значение в таблице ITEMVALUE
, и, если ничего не найдено, присоединитесь к таблице ITEMHIERARCHY
, чтобы получить все SUBITEMs
, составляющие верхний уровень ITEMs
. Затем я хотел бы рекурсивно искать в таблице ITEMVALUE
совпадение SUBITEM-VALUE
или, если ничего не найдено, извлечь SUBITEMs
из таблицы ITEMHIERARCHY
.
Первый набор LEFT-JOINs
работают, но не те, что под UNION ALL
, что дает мне ошибку:
SQL compilation error: OUTER JOINs with a self reference are not allowed in a recursive CTE.
Есть ли лучший способ сделать то, что я пытаюсь сделать в Snowflake
, или я не думаю о это правильно?
В настоящее время я вручную выписал рекурсивные слои на 5 уровней, что означает, что мне нужно добавить уровень, если таблица ITEMHIERARCHY
станет более сложной.