【问题标题】:Is the outer WHERE clause optimized in a Recursive CTE?是否在递归 CTE 中优化了外部 WHERE 子句?
【发布时间】: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


【解决方案1】:

为了能够将 WHERE 子句应用于 CTE 内的查询,需要数据库来证明

  • 所有 第一列中的值都不会被递归更改并返回到基本查询,并且,一般来说,
  • 任何被过滤掉的行都不可能有任何可能出现在查询结果中或以任何其他方式影响 CTE 的子代。

这样的证明者不存在。 请参阅Subquery flattening 的限制 22。

【讨论】:

    【解决方案2】:

    要了解为什么您的第一个查询不是最优的,请尝试使用 UNION ALL 而不是仅使用 UNION 来运行这两个查询。给定样本数据后,第一个将返回 21 行,而第二个仅返回 7 行。

    实际第一个查询中的重复行随后通过执行排序和重复消除来消除,而实际第二个查询中不需要此步骤。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-07
      • 1970-01-01
      • 2012-11-15
      相关资源
      最近更新 更多