【问题标题】:RECURSIVE in SQLSQL 中的递归
【发布时间】:2013-09-21 08:51:38
【问题描述】:

我正在学习 SQL,并且很难理解以下递归 SQL 语句。

WITH RECURSIVE t(n) AS (
    SELECT 1
    UNION ALL
    SELECT n+1 FROM t WHERE n < 100
)
SELECT sum(n) FROM t;

SELECT sum(n) FROM t; 中的 n 和 t 是什么?据我所知,n 是 t 的一个集合。我说的对吗?

还有这个语句中的递归是如何触发的?

【问题讨论】:

  • 不是。 MySQL 不支持with 或递归。你在考虑什么数据库?
  • MySQL 不支持WITH RECURSIVE 语法,因此我稍微扩大了问题范围以避免该问题。 (它被其他各种数据库支持。)
  • t 是一个表,n 是该表的一列。它使用CTE (Common Table Expression) to create recursion。基本上,它从1UNION 中的第一个选择)开始,然后对于每次迭代,它选择最后一个结果 + 1,直到n 等于 100(UNION 的第二部分)。然后,最后一个SELECT(在 CTE 之外)对所有结果求和。不要被这个例子所迷惑,表被称为RECURSIVE,那里没有魔法。这只是名字。
  • @GordonLinoff 感谢您指出这个问题。它应该在 PostgreSQL,而不是 MySQL。我犯了一个错误。
  • @duskwuff 感谢您纠正我的帖子。

标签: sql recursion


【解决方案1】:

您使用的语法类似于 Postgres。 SQL 中的“递归”并不是真正的递归,而是迭代。你的说法是:

WITH RECURSIVE t(n) AS (
    SELECT 1
    UNION ALL
    SELECT n+1 FROM t WHERE n < 100
)
SELECT sum(n) FROM t;

t 的语句被评估为:

  1. 评估非自引用部分 (select 1)。
  2. 然后评估自引用部分。 (最初这给出 2。)
  3. 然后再次评估自引用部分。 (3)。
  4. 在条件仍然有效时以此类推 (n &lt; 100)。

完成后,t 子查询完成,可以评估最终语句。

【讨论】:

    【解决方案2】:

    这称为Common Table Expression 或 CTE。

    查询中的RECURSIVE 没有任何意义:它只是另一个名称,例如nt。使事情递归的是名为 t 的 CTE 在表达式中引用自身。因此,要生成表达式的结果,查询引擎必须递归地构建结果,每次计算都会触发下一次计算。它到达这一点:SELECT n+1 FROM t... 并且必须停止并评估t。为此,它必须再次调用自己,依此类推,直到条件 (n &lt; 100) 不再成立。 SELECT 1 提供了一个起点,WHERE n &lt; 100 使查询不会永远重复。

    至少,它在概念上应该是这样工作的。通常真正发生的是查询引擎迭代地构建结果,而不是递归地构建结果,如果可以的话,但那是另一回事了。

    【讨论】:

    • recursive 确实意味着什么(它不是“另一个名字”)。如果您想要“递归”CTE,SQL 标准要求它。对于常规(非递归)CTE,您必须省略该关键字。
    【解决方案3】:

    让我们分开:

    WITH RECURSIVE t(n) AS (
    

    一个公用表表达式 (CTE),它应该包括一个种子查询和一个递归查询。 CTE 称为 t 并返回 1 列:n

    种子查询:

        SELECT 1
    

    返回 ans 答案集(在本例中只有一行:1)并将其副本放入最终答案集

    现在开始递归部分:

        UNION ALL
    

    现在处理从种子查询返回的行,返回 n+1(同样是单行答案集:2)并复制到最终答案集中:

        SELECT n+1 FROM t WHERE n < 100
    

    如果此步骤返回非空答案集 (activity_count > 0),则会重复(永远)。

    n+1 这样的计算中的 WHERE 条件通常用于避免无限递归。人们通常会根据数据知道可能的最大级别,对于复杂的查询,很容易把某些条件弄错;-)

    最后返回答案集:

    )
    SELECT sum(n) FROM t;
    

    当您简单地执行 SELECT * FROM t; 时,您会看到从 1 到 100 的所有数字,这不是生成此列​​表的一种非常有效的方法。

    要记住的最重要的事情是,每个步骤都会产生最终结果的一部分,并且只有上一步中的那些行会在下一个递归级别中处理。

    【讨论】:

      猜你喜欢
      • 2010-11-22
      • 2020-12-02
      • 1970-01-01
      • 2011-11-09
      • 1970-01-01
      • 1970-01-01
      • 2018-03-12
      • 2010-09-08
      • 1970-01-01
      相关资源
      最近更新 更多