【发布时间】:2020-10-30 13:44:27
【问题描述】:
我正在尝试创建一个依赖于 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 的给定值,但汇总会被忽略。
这是由于UNION ALL 子句中的LEFT JOIN 而导致的递归查询失败的尝试:
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
;
查询的目标是首先从ITEM表中获取所有顶级ITEMs,在ITEMVALUE表中搜索对应的值,如果没有找到,则加入ITEMHIERARCHY检索构成顶级ITEMs 的所有SUBITEMs 的表。然后我想在ITEMVALUE 表上递归搜索SUBITEM-VALUE 匹配,或者,如果没有找到匹配,则从ITEMHIERARCHY 表中检索SUBITEMs。
第一组LEFT-JOINs 工作,但不是UNION ALL 下的那些给我错误:
SQL compilation error: OUTER JOINs with a self reference are not allowed in a recursive CTE.
有没有更好的方法来做我在Snowflake 中尝试做的事情,还是我没有正确考虑这个问题?
目前我手动将递归层写成 5 个级别,这意味着如果 ITEMHIERARCHY 表变得更复杂,我必须添加一个级别。
【问题讨论】:
标签: sql left-join snowflake-cloud-data-platform recursive-query