递归 CTE 如何逐行运行?

2023-12-13

我想我已经掌握了递归 CTE 的格式,足以编写一个,但仍然发现自己非常沮丧,因为我无法手动处理一个(假装自己是 SQL 引擎并用笔和纸到达结果集) 。我找到了这个,这与我正在寻找的内容很接近,但不够详细。我可以毫无问题地跟踪 C++ 递归函数并理解它是如何运行的——但对于 SQL,我不明白引擎为什么或如何知道停止。锚点和递归块是否每次都会被调用,或者锚点是否在以后的迭代中被跳过? (我对此表示怀疑,但我试图表达我对它似乎跳跃的方式的困惑。)如果每次都调用锚点,那么锚点如何在最终结果中不会出现多次?我希望有人可以分解第 1 行、第 2 行等,随着结果集的积累,会发生什么以及“内存中”的内容。

我冒昧地偷了我的此页面的示例,因为它似乎是最容易理解的。

DECLARE @tbl TABLE ( 
      Id INT 
    , [Name] VARCHAR(20) 
    , ParentId INT 
) 

INSERT INTO @tbl( Id, Name, ParentId ) 
VALUES 
     (1, 'Europe', NULL) 
    ,(2, 'Asia',   NULL) 
    ,(3, 'Germany',   1) 
    ,(4, 'UK',        1) 
    ,(5, 'China',     2) 
    ,(6, 'India',     2) 
    ,(7, 'Scotland',  4) 
    ,(8, 'Edinburgh', 7) 
    ,(9, 'Leith',     8)  
; 

WITH abcd 
    AS ( 
        -- anchor 
        SELECT  id, Name, ParentID, 
                CAST(Name AS VARCHAR(1000)) AS Path 
        FROM    @tbl 
        WHERE   ParentId IS NULL 
        UNION ALL 
          --recursive member 
        SELECT  t.id, t.Name, t.ParentID, 
                CAST((a.path + '/' + t.Name) AS VARCHAR(1000)) AS "Path"
        FROM    @tbl AS t 
                JOIN abcd AS a 
                  ON t.ParentId = a.id 
       )
SELECT * FROM abcd 

想一个递归CTE如同无尽的UNION ALL:

WITH    rows AS
        (
        SELECT  *
        FROM    mytable
        WHERE   anchor_condition
        ),
        rows2 AS
        (
        SELECT  *
        FROM    set_operation(mytable, rows)
        ),
        rows3 AS
        (
        SELECT  *
        FROM    set_operation(mytable, rows2)
        ),
        …
SELECT  *
FROM    rows
UNION ALL
SELECT  *
FROM    rows2
UNION ALL
SELECT  *
FROM    rows3
UNION ALL
…

在你的情况下,那就是:

WITH    abcd1 AS
        ( 
        SELECT  *
        FROM    @tbl t
        WHERE   ParentId IS NULL 
        ),
        abcd2 AS
        ( 
        SELECT  t.*
        FROM    abcd1
        JOIN    @tbl t
        ON      t.ParentID = abcd1.id
        ),
        abcd3 AS
        ( 
        SELECT  t.*
        FROM    abcd2
        JOIN    @tbl t
        ON      t.ParentID = abcd2.id
        ),
        abcd4 AS
        ( 
        SELECT  t.*
        FROM    abcd3
        JOIN    @tbl t
        ON      t.ParentID = abcd3.id
        ),
        abcd5 AS
        ( 
        SELECT  t.*
        FROM    abcd4
        JOIN    @tbl t
        ON      t.ParentID = abcd4.id
        ),
        abcd6 AS
        ( 
        SELECT  t.*
        FROM    abcd5
        JOIN    @tbl t
        ON      t.ParentID = abcd5.id
        )
SELECT  *
FROM    abcd1
UNION ALL
SELECT  *
FROM    abcd2
UNION ALL
SELECT  *
FROM    abcd3
UNION ALL
SELECT  *
FROM    abcd4
UNION ALL
SELECT  *
FROM    abcd5
UNION ALL
SELECT  *
FROM    abcd6

Since abcd6没有产生任何结果,这意味着停止条件。

理论上,递归CTE可以是无限的,但实际上,SQL Server尝试禁止会导致无限记录集的查询。

您可能想阅读这篇文章:

  • SQL Server:递归 CTE 真的是基于集合的吗?
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

递归 CTE 如何逐行运行? 的相关文章

随机推荐

  • Entity Framework 5 和 Amazon RDS - “底层提供程序在 Open 时失败。”

    我有一个 C Entity Framework Web 应用程序 可以在本地 SQL 2012 数据库上正常运行 我将数据库复制到新的 RDS 实例 并且可以通过 Visual Studio 和 SQL Server Management
  • PHP 不区分大小写和重音的数组搜索

    我有一个包含单词的数组 其中一些带有重音符号 我想测试给定的单词是否在该数组中 但使其不区分大小写和重音 例如 array array coche cami n moto carro 我想要一个简单的小功能 比如in array 如果我的字
  • 您可以在 WPF 应用程序中使用 jQuery 吗?

    在过去的几个月里 我一直在创建一个 WPF 应用程序 我想向我的应用程序添加一些动画 之前有人告诉我 jQuery 是一个很好的用于动画的 Javascript 库 问题是 环顾四周后 互联网上没有太多东西让我知道这是否可行 我对 jQue
  • 为什么在访问整数时缓冲区溢出会导致分段错误?

    在函数 A 调用函数 B 期间 B 分配一个 100 个字符的数组并多次填充它 其中一次使用 101 个字符的字符串 一次使用 110 个字符的字符串 这是一个明显的错误 随后 函数 A 尝试访问完全不相关的 int 变量 i 并发生分段错
  • 有关 C# 4.0 中的代码契约的书籍 [已关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心以获得指导 虽然我已经了解代码契约有一
  • Outlook 无法识别 ics 消息

    我正在尝试在 PHP 中创建一个 ics 文件 并将其邮寄给用户 该解决方案在 Gmail 中运行良好 我收到了一份精美的邀请 所有信息都出现在正确的位置 但 Outlook 似乎根本无法识别它 我收到一封没有附件的空电子邮件 据我所知 没
  • Windows 上的卷曲

    我已关注此链接上的所有内容 如何在 Windows 上安装 设置和使用 cURL 但我无法安装最新的curl 7 50 3https curl haxx se download html 在 Windows 7 2008 Server R2
  • 在方向更改时从双窗格切换到单窗格维护片段堆栈

    目前 我在平板电脑上有横向和纵向的双窗格布局 与设置类似 我有一个活动将片段加载到左侧选择窗格中 然后在显示的任何右侧片段中所做的选择都会导致更多片段显示到右侧窗格中 并一直添加到后台堆栈 现在我可以看到 对于某些平板电脑来说 使用一个用于
  • UAC 风格的提升提示

    我有兴趣在临时会话中启动一个窗口 就像 UAC 提示的显示方式一样 有些人对这个概念感兴趣 所以我想我应该在这里问 本质上 我们想要的是一个像UAC 你确定要 提示一样的提升窗口 但具有任意窗口 最终目标是防止窗口事件挂钩以及密码输入期间可
  • 正则表达式在字符串中查找 Youtube 链接[重复]

    这个问题在这里已经有答案了 我有一个这样的字符串 Lorem Ipsum is simply dummy text of the printing and typesetting industry Lorem Ipsum has been
  • 为什么我的 cfloop 在插入第一个 id 后停止?

    我创建了 cfloop 它会执行我在循环上方创建的查询 在循环内部 我有另一个定义值的循环 然后使用 insert 语句进行 cfquery 在尝试将记录插入数据库之前 我测试了循环 一切看起来都很好 当我尝试应用它来插入我的记录后 我的插
  • Rails Cocoon gem 没有错误,也没有输出

    我正在使用 cocoon gem 开发动态嵌套表单 我有两个型号 class CrossTable lt ActiveRecord Base attr accessible title table name database folder
  • Java-Client PHP-Server UDP打洞示例代码

    我正在开发一个需要 ea p2p 服务器的项目 但我还没有找到任何 java client php server 示例代码 我了解 udp 打孔工作原理的概念 但我无法在代码中执行任何操作 我尝试过的 TheSocket java publ
  • 在 Qt-Creator SDK 上以 root 身份运行代码

    我使用 Qt Creator 2 5 2 SDK 在 Linux 上开发 C 代码 当从 SDK 界面 例如 ctrl R 运行代码时 如何以 root 身份运行代码 以 root 身份运行 Qt Creator 的最简单解决方案 老实说
  • 通过迁移创建动态审计表

    使用 Net Core 2 1 和 Audit NET EF 12 1 10 我尝试添加包含审核表的迁移 但调用 Add Migration 时 迁移中不会生成审核表 我假设使用 动态 审核会自动完成此操作 我没有任何审计接口 我将其留给
  • 谷歌应用程序脚本;文件;将所选元素转换为 HTML

    我刚刚开始使用 Google Apps 脚本并遵循插件快速入门 https developers google com apps script quickstart docs 在快速入门中 您可以创建一个简单的插件来从文档中获取选择并使用
  • ASP.NET 使用 MVC 将 linq 查询结果绑定到 HTML.DropDownList()

    我正在尝试使用单个数据库调用构建一个下拉列表 我的表由 Id 列和 CompanyName 列组成 我需要向用户显示公司名称 并在选择公司名称时将页面的 Id 设置为 Id 我建立了一个简单的模型来存储信息 using System usi
  • 如何获取右键单击事件javascript [重复]

    这个问题在这里已经有答案了 可能的重复 如何使用 JavaScript 检测鼠标右键单击 粘贴 当有人右键单击然后粘贴后粘贴时如何捕获事件 当有人在右键单击并粘贴后将任何内容粘贴到文本框中时 我想发出警报 在javascript中 有什么方
  • 更改 ListView 项目的文本颜色

    如何更改添加到项目的文本颜色ListView 我需要根据某些条件以编程方式更改代码中的颜色 并将不同的行更改为不同的文本颜色 例如 行 0 红色 行 1 白色 行 3 蓝色等 在xml布局中设置文本颜色无法满足我的要求 这是我的代码 Ove
  • 递归 CTE 如何逐行运行?

    我想我已经掌握了递归 CTE 的格式 足以编写一个 但仍然发现自己非常沮丧 因为我无法手动处理一个 假装自己是 SQL 引擎并用笔和纸到达结果集 我找到了这个 这与我正在寻找的内容很接近 但不够详细 我可以毫无问题地跟踪 C 递归函数并理解