使用以下表定义:
CREATE TABLE Nodes(id INTEGER, child INTEGER);
INSERT INTO Nodes(id, child) VALUES(1, 10);
INSERT INTO Nodes(id, child) VALUES(1, 11);
INSERT INTO Nodes(id, child) VALUES(1, 12);
INSERT INTO Nodes(id, child) VALUES(10, 100);
INSERT INTO Nodes(id, child) VALUES(10, 101);
INSERT INTO Nodes(id, child) VALUES(10, 102);
INSERT INTO Nodes(id, child) VALUES(2, 20);
INSERT INTO Nodes(id, child) VALUES(2, 21);
INSERT INTO Nodes(id, child) VALUES(2, 22);
INSERT INTO Nodes(id, child) VALUES(20, 200);
INSERT INTO Nodes(id, child) VALUES(20, 201);
INSERT INTO Nodes(id, child) VALUES(20, 202);
使用以下查询:
WITH RECURSIVE members(base, id, level) AS (
SELECT n1.id, n1.id, 0
FROM Nodes n1
LEFT OUTER JOIN Nodes n2 ON n2.child = n1.id
WHERE n2.id IS NULL
UNION
SELECT m.base, n.child, m.level + 1
FROM members m
INNER JOIN Nodes n ON m.id=n.id
)
SELECT m.id, m.level
FROM members m
WHERE m.base IN (1)
外部WHERE子句是否在递归CTE中优化?我考虑使用的替代方案是:
WITH RECURSIVE members(id, level) AS (
VALUES (1, 0)
UNION
SELECT n.child, m.level + 1
FROM members m
INNER JOIN Nodes n ON m.id=n.id
)
SELECT m.id, m.level
FROM members m
但它存在无法创建视图的问题。因此,如果两者之间的性能差异很小,我更喜欢从递归CTE创建一个视图,然后只是查询它。
答案 0 :(得分:1)
为了能够将WHERE子句应用于CTE内的查询,数据库将需要证明
这样的证明者不存在。 请参阅Subquery flattening的限制22。
答案 1 :(得分:0)
要了解您的第一个查询不是最佳查询的原因,请尝试使用UNION ALL而不是UNION运行它们。在给出样本数据的情况下,第一行将返回21行,而第二行仅返回7.
实际的第一个查询中的重复行随后通过执行排序和重复删除来消除,而在实际的第二个查询中不需要此步骤。