`

sql server 树形表非循环递归查询

阅读更多

http://www.cnblogs.com/infozr/archive/2012/12/27/2835084.html

http://www.cnblogs.com/cracker/archive/2012/07/07/2580781.html

http://tech.techweb.com.cn/viewthread.php?tid=245729

http://jc-dreaming.iteye.com/blog/772030

http://technet.microsoft.com/zh-cn/library/ms186243(v=sql.105).aspx

 

 

SQL Server 树形表非循环递归查询

很多人可能想要查询整个树形表关联的内容都会通过循环递归来查...事实上在微软在SQL2005或以上版本就能用别的语法进行查询,下面是示例。
 
--通过子节点查询父节点 WITH TREE AS(     SELECT * FROM Areas     WHERE id = 6
-- 要查询的子 id     UNION ALL     SELECT Areas.* FROM Areas, TREE     WHERE TREE.PId = Areas.Id ) SELECT Area FROM TREE
 
--通过父节点查询子节点 WITH TREE AS(     SELECT * FROM Areas     WHERE id = 7
  -- 要查询的子 id     UNION ALL     SELECT Areas.* FROM Areas, TREE     WHERE TREE.Id = Areas.PId ) SELECT Area FROM TREE
 
通过子节点查询父节点查询结果为:
图片
修改代码为
 
--通过子节点查询父节点 declare @area varchar(8000); WITH TREE AS(     SELECT * FROM Areas     WHERE id = 6 
-- 要查询的子 id     UNION ALL     SELECT Areas.* FROM Areas, TREE     WHERE TREE.PId = Areas.Id ) select @area=isnull(@area,'')+Area from Tree order by id select Area= @area
 
则结果为:中国北京市丰台区
 
根据以上可以将这段代码封装为一个存储过程
 
-----存储过程,递归获取树形地区表字符串 if exists (select * from sysobjects where name='SP_GetAreaStr') drop proc SP_GetAreaStr go create procedure SP_GetAreaStr @id int as declare @area varchar(8000) begin WITH TREE AS(     SELECT * FROM Areas     WHERE id = @id
-- 要查询的子 id     UNION ALL     SELECT Areas.* FROM Areas, TREE     WHERE TREE.PId = Areas.Id ) select @area=isnull(@area,'')+Area from Tree order by id select Area= @area end go
--exec sp_helptext 'SP_GetAreaStr' --go exec SP_GetAreaStr 28 go
 
查询结果:中国安徽省宿州市灵璧县
 
所用表结构:
图片
部分数据:
图片
 
 
 

使用公用表表达式的递归查询

SQL Server 2008 R2
 
其他版本
 
0(共 1)对本文的评价是有帮助 评价此主题
 

 

公用表表达式 (CTE) 具有一个重要的优点,那就是能够引用其自身,从而创建递归 CTE。递归 CTE 是一个重复执行初始 CTE 以返回数据子集直到获取完整结果集的公用表表达式。

当某个查询引用递归 CTE 时,它即被称为递归查询。递归查询通常用于返回分层数据,例如:显示某个组织图中的雇员或物料清单方案(其中父级产品有一个或多个组件,而那些组件可能还有子组件,或者是其他父级产品的组件)中的数据。

递归 CTE 可以极大地简化在 SELECT、INSERT、UPDATE、DELETE 或 CREATE VIEW 语句中运行递归查询所需的代码。在 SQL Server 的早期版本中,递归查询通常需要使用临时表、游标和逻辑来控制递归步骤流。有关公用表表达式的详细信息,请参阅使用公用表表达式

Transact-SQL 中的递归 CTE 的结构与其他编程语言中的递归例程相似。尽管其他语言中的递归例程返回标量值,但递归 CTE 可以返回多行。

递归 CTE 由下列三个元素组成:

  1. 例程的调用。

    递归 CTE 的第一个调用包括一个或多个由 UNION ALL、UNION、EXCEPT 或 INTERSECT 运算符联接的 CTE_query_definitions。由于这些查询定义形成了 CTE 结构的基准结果集,所以它们被称为“定位点成员”。

    CTE_query_definitions 被视为定位点成员,除非它们引用了 CTE 本身。所有定位点成员查询定义必须放置在第一个递归成员定义之前,而且必须使用 UNION ALL 运算符联接最后一个定位点成员和第一个递归成员。

  2. 例程的递归调用。

    递归调用包括一个或多个由引用 CTE 本身的 UNION ALL 运算符联接的 CTE_query_definitions。这些查询定义被称为“递归成员”。

  3. 终止检查。

    终止检查是隐式的;当上一个调用中未返回行时,递归将停止。

注意注意

如果递归 CTE 组合不正确,可能会导致无限循环。例如,如果递归成员查询定义对父列和子列返回相同的值,则会造成无限循环。在测试递归查询的结果时,可以通过在 INSERT、UPDATE、DELETE 或 SELECT 语句的 OPTION 子句中使用 MAXRECURSION 提示和 0 到 32,767 之间的值,来限制特定语句允许的递归级数。有关详细信息,请参阅查询提示 (Transact-SQL) 和 WITH common_table_expression (Transact-SQL)

伪代码和语义

递归 CTE 结构必须至少包含一个定位点成员和一个递归成员。以下伪代码显示了包含一个定位点成员和一个递归成员的简单递归 CTE 的组件。

WITH cte_name ( column_name [,...n] )

AS

(

CTE_query_definition –- Anchor member is defined.

UNION ALL

CTE_query_definition –- Recursive member is defined referencing cte_name.

)

-- Statement using the CTE

SELECT *

FROM cte_name

递归执行的语义如下:

  1. 将 CTE 表达式拆分为定位点成员和递归成员。

  2. 运行定位点成员,创建第一个调用或基准结果集 (T0)。

  3. 运行递归成员,将 Ti 作为输入,将 Ti+1 作为输出。

  4. 重复步骤 3,直到返回空集。

  5. 返回结果集。这是对 T0 到 Tn 执行 UNION ALL 的结果。

以下示例通过返回 Adventure Works Cycles 公司的雇员的分层列表(从最高级雇员开始)显示递归 CTE 结构的语义。示例后面是代码执行的演练。

 
-- Create an Employee table.
CREATE TABLE dbo.MyEmployees
(
	EmployeeID smallint NOT NULL,
	FirstName nvarchar(30)  NOT NULL,
	LastName  nvarchar(40) NOT NULL,
	Title nvarchar(50) NOT NULL,
	DeptID smallint NOT NULL,
	ManagerID int NULL,
 CONSTRAINT PK_EmployeeID PRIMARY KEY CLUSTERED (EmployeeID ASC) 
);
-- Populate the table with values.
INSERT INTO dbo.MyEmployees VALUES 
 (1, N'Ken', N'Sánchez', N'Chief Executive Officer',16,NULL)
,(273, N'Brian', N'Welcker', N'Vice President of Sales',3,1)
,(274, N'Stephen', N'Jiang', N'North American Sales Manager',3,273)
,(275, N'Michael', N'Blythe', N'Sales Representative',3,274)
,(276, N'Linda', N'Mitchell', N'Sales Representative',3,274)
,(285, N'Syed', N'Abbas', N'Pacific Sales Manager',3,273)
,(286, N'Lynn', N'Tsoflias', N'Sales Representative',3,285)
,(16,  N'David',N'Bradley', N'Marketing Manager', 4, 273)
,(23,  N'Mary', N'Gibson', N'Marketing Specialist', 4, 16);


 
USE AdventureWorks2008R2;
GO
WITH DirectReports (ManagerID, EmployeeID, Title, DeptID, Level)
AS
(
-- Anchor member definition
    SELECT e.ManagerID, e.EmployeeID, e.Title, edh.DepartmentID, 
        0 AS Level
    FROM dbo.MyEmployees AS e
    INNER JOIN HumanResources.EmployeeDepartmentHistory AS edh
        ON e.EmployeeID = edh.BusinessEntityID AND edh.EndDate IS NULL
    WHERE ManagerID IS NULL
    UNION ALL
-- Recursive member definition
    SELECT e.ManagerID, e.EmployeeID, e.Title, edh.DepartmentID,
        Level + 1
    FROM dbo.MyEmployees AS e
    INNER JOIN HumanResources.EmployeeDepartmentHistory AS edh
        ON e.EmployeeID = edh.BusinessEntityID AND edh.EndDate IS NULL
    INNER JOIN DirectReports AS d
        ON e.ManagerID = d.EmployeeID
)
-- Statement that executes the CTE
SELECT ManagerID, EmployeeID, Title, DeptID, Level
FROM DirectReports
INNER JOIN HumanResources.Department AS dp
    ON DirectReports.DeptID = dp.DepartmentID
WHERE dp.GroupName = N'Sales and Marketing' OR Level = 0;
GO


示例代码演练

  1. 递归 CTE DirectReports 定义了一个定位点成员和一个递归成员。

  2. 定位点成员返回基准结果集 T0。这就是公司中的最高级雇员,即不向经理报告的雇员。

    以下是定位点成员返回的结果集:

     
     
    ManagerID EmployeeID Title                         Level
    --------- ---------- ----------------------------- ------
    NULL      1          Chief Executive Officer        0
    
  3. 递归成员返回定位点成员结果集中的雇员的直接下属。这是通过在 Employee 表和 DirectReports CTE 之间执行联接操作获得的。正是此次对 CTE 自身的引用建立了递归调用。利用 CTE DirectReports 中的雇员作为输入 (Ti),联接 (MyEmployees.ManagerID = DirectReports.EmployeeID) 返回经理为 (Ti) 的雇员作为输出 (Ti+1)。这样,递归成员的第一次迭代返回了以下结果集:

     
     
    ManagerID EmployeeID Title                         Level
    --------- ---------- ----------------------------- ------
    1         273        Vice President of Sales       1
    
  4. 重复激活递归成员。递归成员的第二次迭代使用步骤 3 中的单行结果集(包含 EmployeeID273)作为输入值,并返回以下结果集:

     
     
    ManagerID EmployeeID Title                         Level
    --------- ---------- ----------------------------- ------
    273       16         Marketing Manager             2
    273       274        North American Sales Manager  2
    273       285        Pacific Sales Manager         2
    

    递归成员的第三次迭代使用上面的结果集作为输入值,并返回以下结果集:

     
     
    ManagerID EmployeeID Title                         Level
    --------- ---------- ----------------------------- ------
    16        23         Marketing Specialist          3
    274       275        Sales Representative          3
    274       276        Sales Representative          3
    285       286        Sales Representative          3
    
  5. 正在运行的查询返回的最终结果集是定位点成员和递归成员生成的所有结果集的并集。

    以下是示例返回的完整结果集:

     
     
    ManagerID EmployeeID Title                         Level
    --------- ---------- ----------------------------- ------
    NULL      1          Chief Executive Officer       0
    1         273        Vice President of Sales       1
    273       16         Marketing Manager             2
    273       274        North American Sales Manager  2
    273       285        Pacific Sales Manager         2
    16        23         Marketing Specialist          3
    274       275        Sales Representative          3
    274       276        Sales Representative          3
    285       286        Sales Representative          3
分享到:
评论

相关推荐

    SQL Server 树形表非循环递归查询的实例详解

    SQL Server从2005版开始引入了一种新的查询方式——递归公共表表达式(Recursive Common Table Expression, CTE),它可以高效地处理树形查询,无需循环。 递归CTE的核心在于`WITH`关键字,它允许我们定义一个临时...

    sqlserver实现树形结构递归查询(无限极分类)的方法

    在SQL Server中,实现树形结构递归查询是数据库管理中的常见需求,特别是在处理具有层级关系的数据时,如无限级分类。SQL Server 2005及以后版本引入了公用表表达式(CTE,Common Table Expression)来支持递归查询...

    MS SQL Server树形结构表遍历的循环算法.pdf

    但是,MS SQL Server在当时尚未内置递归查询功能,这意味着在MS SQL Server上实现树形结构表的遍历查询需要采取其他方法。 文章中提出了在MS SQL Server上实现树遍历查询的循环算法。这一算法的提出基于对树遍历...

    SQLserver2008使用表达式递归查询

    在你可能感兴趣的相关文章中,可以看到更多关于如何在SQL Server中使用递归查询的例子,包括递归子节点、父节点,查询表结构,非循环递归查询,以及处理树形结构的方法等。学习和掌握这些技术,将有助于你更有效地...

    sql递归查询实例2

    根据提供的信息,我们可以深入探讨如何使用SQL递归查询来获取所有属于特定`upperid`的数据及其子树。这里的关键在于理解递归查询的工作原理,并通过一个具体的例子来演示这一过程。 ### SQL递归查询概念 在关系型...

    sql_函数实现三种父子递归

    在SQL Server 2005及以上版本,还可以使用公用表表达式(CTE)进行递归查询,以更简洁的方式完成相同的功能。 2. 查找所有父节点(反向递归): 与查找子节点相反,我们从一个节点开始,向上查找其所有父节点直至根...

    数据库设计之递归树查询

    本文将深入探讨如何通过递归查询来解决这类问题,并着重讲解使用`WITH`语句来实现递归查询的方法,适用于多种数据库系统,如MySQL、PostgreSQL、SQL Server等。 一、理解递归查询 递归查询是一种在数据库中遍历层级...

    使用SqlServer CTE递归查询处理树、图和层次结构

    总的来说,使用SQL Server的CTE递归查询可以帮助我们有效地处理树形和层次结构数据,简化复杂查询的编写,同时保持代码的可读性和高性能。在设计数据库查询时,理解并掌握递归CTE的使用,对于处理具有层次关系的数据...

    sql server实现递归查询的方法示例

    在SQL Server中,递归查询是一种处理层次结构数据的有效方法,尤其适用于树形结构的数据模型。递归查询允许我们从一个起始点开始,沿着层级关系遍历直到达到指定条件或者遍历完所有关联的记录。在SQL Server中,递归...

    SQL Server 公用表表达式(CTE)实现递归的方法

    SQL Server中的公用表表达式(CTE,Common Table Expression)是一种强大的工具,它允许你在复杂的查询中定义一个临时的结果集,这个结果集可以被查询本身多次引用。CTE的使用非常灵活,尤其在处理递归关系时表现得...

    SQL With 递归

    在SQL中,`WITH`语句,也称为公共表表达式(Common Table Expression,简称CTE),是一种非常有用的工具,特别是在处理递归查询时。它允许我们定义一个临时的结果集,这个结果集可以在同一个查询中被多次引用,提高...

    Microsoft SQL Server中T-SQL关于树(层次)结构的处理研究.pdf

    用户自定义函数可以在数据库中封装业务逻辑,而递归公用表表达式则是一种强大的递归查询机制,它能够处理具有自引用关系的数据表,这一点在树形数据结构的处理中尤其有用。 在具体实现上,文章提出了一个使用场景...

    sqlserver中存储过程的递归调用示例

    在存储过程中实现递归调用可以解决某些复杂问题,如树形结构的遍历、阶层计算等。 本示例中的存储过程名为`usp_spFactorial`,其功能是计算输入整数(@InputValue)的阶乘。阶乘是一个数学运算,表示从1乘到指定正...

    深入sql oracle递归查询

    在SQL中,递归查询是一种强大的工具,尤其在处理层级数据或者树形结构时非常有用。Oracle数据库系统提供了两种主要的递归查询方法:一种是使用`WITH`子句配合`UNION ALL`,另一种是使用`START WITH`和`CONNECT BY`。...

    SQL SERVER 无级机构树实例

    ”明确指出本篇内容将聚焦于如何在SQL Server中构建和查询树形结构数据,特别是一种无级别的树结构。这种结构允许每个节点有任意数量的子节点,并且任何节点都可以成为其他节点的父节点,形成复杂的层次关系。 ### ...

    Sqlserver2000经典脚本

    介绍就不多说了,下边是部分目录,觉得有用的话就顶一个 C:. │ sqlserver2000.txt │ ├─第01章 │ 1.9.1 设置内存选项.sql │ 1.9.2(2) 使用文件及文件组.sql │ 1.9.2(3) 调整...

    Inside Microsoft SQL Server 2008 - TSQL Querying

    书中详细讨论了如何在SQL Server中处理这些复杂的数据结构,并提供了具体的实例来演示如何编写递归查询来遍历这些结构,以便于进行高级数据分析。 #### 八、利用纯逻辑谜题提高问题解决能力 为了帮助读者进一步...

    用SQL实现树的查询

    在关系型数据库中,如SQL Server 2000,处理树形结构的数据是一项挑战。树形结构的数据通常体现在层级关系上,比如组织架构、产品分类等,每个节点都有可能拥有子节点。在SQL中查询这类数据时,我们需要利用特定的...

Global site tag (gtag.js) - Google Analytics