【发布时间】:2014-09-28 04:31:17
【问题描述】:
有如下表定义:
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)
是否在递归 CTE 中优化了外部 WHERE 子句?我考虑使用的替代方法是:
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 创建一个视图,然后只查询它。
【问题讨论】:
-
VALUES 语句的其余部分在哪里?它需要有两个元素。
-
@PieterGeerkens 是的,它是用
(_ID_, 0),动态填充的,每个 id 都重复。因此,第二个查询假设只有根节点 id 被传入,并且不会自行检查。 -
哦!我没有意识到
%s是一个被引擎解释为whatever is needed, correctly of course的魔术字符串。 -
@PieterGeerkens 我很抱歉,
%s是一个典型的在这里填写内容的短语,我认为这对这个问题来说不是很重要。如果我让你感到困惑,我很抱歉。我更改了它以使其更清晰。
标签: sql sqlite recursive-cte