SQL Server 2005中的CTE递归查询得到一棵树
感觉这个CTE递归查询蛮好用的,先举个例子:
- use City;
- go
- create table Tree
- (
- ID int identity(1,1) primary key not null,
- Name varchar(20) not null,
- Parent varchar(20) null
- )
- go
- insert Tree values('大学',null)
- insert Tree values('学院','大学')
- insert Tree values('计算机学院','学院')
- insert Tree values('网络工程','计算机学院')
- insert Tree values('信息管理','计算机学院')
- insert Tree values('电信学院','学院')
- insert Tree values('教务处','大学')
- insert Tree values('材料科','教务处')
- insert Tree values('招生办','大学')
- go
- with CTE as
- (
- -->Begin 一个定位点成员
- select ID, Name,Parent,cast(Name as nvarchar(max)) as TE,0 as Levle from Tree where Parent is null
- -->End
- union all
- -->Begin一个递归成员
- select Tree.ID, Tree.Name,Tree.Parent,cast(replicate(' ',len(CTE.TE))+'|_'+Tree.name as nvarchar(MAX)) as TE,Levle+1 as Levle
- from Tree inner join CTE
- on Tree.Parent=CTE.Name
- -->End
- )
- select * from CTE order by ID
- --1.将 CTE 表达式拆分为定位点成员和递归成员。
- --2.运行定位点成员,创建第一个调用或基准结果集 (T0)。
- --3.运行递归成员,将 Ti 作为输入(这里只有一条记录),将 Ti+1 作为输出。
- --4.重复步骤 3,直到返回空集。
- --5.返回结果集。这是对 T0 到 Tn 执行 UNION ALL 的结果。
上面的SQL语句再次插入一条数据:
insert Tree values('网络1班','网络工程')
运行结果如下图:

图1 运行结果
注意点:貌似在递归成员处所选择的字段都必须Tree表的数据,而不能是CTE结果集中的除了Tree中没有而CTE中有的字段在这里才可以引用,比如字段TE。
首先看下,遍历的第1条记录的SQL语句:
- select ID, Name,Parent,cast(Name as nvarchar(max)) as TE,0 as Levle from Tree where Parent is null
获取的结果为:
Name Parent TE Levle
-------------------------------------
大学 NULL 大学 0
递归第2次所获取的结果集合的类SQL语句为:
- select Tree.ID, Tree.Name,Tree.Parent,cast(replicate(' ',len(CTE.TE))+'|_'+Tree.name as nvarchar(MAX)) as TE,Levle+1 as Levle
- from Tree inner join
- (select ID, Name,Parent,cast(Name as nvarchar(max)) as TE,0 as Levle from Tree where Parent is null)
- as CTE
- on Tree.Parent=CTE.Name
上面的CTE子查询的结果就是第一次递归查询的结果集,上面SQL运行结果为:

同样的,将第二次递归查询的上面三条记录作为第三次查询的‘定位成员’:
【这里要注意,上面的三条记录是从最后一条开始依次作为第三次递归的输入的,即第一条是ID=9的记录,接下来是7和2,关于第四次递归也类似】
第三次递归类SQL语句
- select Tree.ID, Tree.Name,Tree.Parent,cast(replicate(' ',len(CTE.TE))+'|_'+Tree.name as nvarchar(MAX)) as TE,Levle+1 as Levle
- from Tree inner join
- (第二次递归查询的SQL语句)as CTE
- on Tree.Parent=CTE.Name
结果如下:

其实每次递归的类SQL可为如下所示:
- select Tree.ID, Tree.Name,Tree.Parent,cast(replicate(' ',len(CTE.TE))+'|_'+Tree.name as nvarchar(MAX)) as TE,Levle+1 as Levle
- from Tree inner join
- (上次递归查询的结果集,仅仅是上次那一次的,而不是以前的总和结果集)
- as CTE
- on Tree.Parent=CTE.Name
第四次递归一次类推,最后所查询的结果为上面所有递归的union。
续:在上面的SQ语句查询结果中,ID为10的记录应该要放在ID为4的后面。
往数据表中再次添加两条记录:
insert Tree values('计科','计算机学院')
insert Tree values('我','网络1班')
再次修改上面的SQL语句:
- with CTE as
- (
- -->Begin 一个定位点成员
- select ID, Name,Parent,cast(Name as nvarchar(max)) as TE,
- ROW_NUMBER()over(order by getdate()) as OrderID
- --最关键是上面这个字段,要获取排序字段,按字符串来排序。
- --其中窗口函数必须要使用order by,但是不能用整型,那就用时间吧
- from Tree where Parent is null
- -->End
- union all
- -->Begin一个递归成员
- select Tree.ID, Tree.Name,Tree.Parent,cast(replicate(' ',len(CTE.TE))+'|_'+Tree.name as nvarchar(MAX)) as TE,
- CTE.OrderID*100+ROW_NUMBER()over(Order by GETDATE()) as OrderID
- from Tree inner join CTE
- on Tree.Parent=CTE.Name
- -->End
- )
- select * from CTE
- order by LTRIM(OrderID)--最后将这个整型数据转换为字符串型的进行排序
- --有时候整型可以比大小,字符串也可以,字符串比的大小是一位一位进行字符比较的
- --整型+字符串==整型,只有字符串+字符串==两个字符串的并和
- --递归查询中:第二条记录可以引用第一条记录的值
- --动态加载记录时,同一个等级的记录识别符:RowNumber()over(order by getdate())
- --延伸:可以动态获取某个部门下的所以子部门。也可以获取该部门上级的所以部门
- --总结:首先要拼凑出一个整型数据,然后转换为字符串,最后是进行字符串的order,而不是整型数据的order,
最后的结果为:

图2 运行结果
这样,无论用户插入多少条记录都可以进行按部门,按规律进行查询。
SQL Server 2005中的CTE递归查询得到一棵树的更多相关文章
- SQL Server 2008中的CTE递归查询得到一棵树
ROW_NUMBER() OVER()函数用法 with CTE as ( -->Begin 一个定位点成员 select ID, Name,Parent,cast ...
- SQLServer2005中的CTE递归查询得到一棵树
最近研究了一下CTE递归查询,感觉这个CTE递归查询蛮好用的,在网上找到了一个比较好的例子,测试例子如下 use City; go create table Tree ( ID ,) primary ...
- SQL Server 2005中的分区表
记录笔记: 转自 猪八戒学做网站 SQL Server 2005中的分区表(一):什么是分区表?为什么要用分区表?如何创建分区表? SQL Server 2005中的分区表(二):如何添加.查询.修改 ...
- SQL Server 2005中更改sa的用户名和密码
修改数据库SA账号名称的代码如下: 代码如下: Alter LOGIN sa DISABLE Alter LOGIN sa WITH NAME = [systemAccount] "sys ...
- SQL Server 2005 中实现通用的异步触发器架构
在SQL Server 2005中,通过新增的Service Broker可以实现异步触发器的处理功能.本文提供一种使用Service Broker实现的通用异步触发器方法. 在本方法中,通过Serv ...
- SQL SERVER 2005中同义词实例
From : http://www.cnblogs.com/jackyrong/archive/2006/11/15/561287.html 在SQL SERVER 2005中,终于出现了同义词了,大 ...
- SQL Server 2005中的分区表(六):将已分区表转换成普通表(转)
我的俄罗斯名叫作“不折腾不舒服斯基”,所以,不将分区表好好折腾一下,我就是不舒服. 在前面,我们介绍过怎么样直接创建一个分区表,也介绍过怎么将一个普通表转换成一个分区表.那么,这两种方式创建的表有什么 ...
- 浅析SQL Server 2005中的主动式通知机制
一.引言 在开发多人同时访问的Web应用程序(其实不只这类程序)时,开发人员往往会在缓存策略的设计上狠下功夫.这是因为,如果将这种环境下不常变更的数据临时存放在应用程序服务器或是用户机器上的话,可以避 ...
- SQL Server 2005中的CHECKSUM功能
原文:SQL Server 2005中的CHECKSUM功能 转自此处 页面 checksum 是SQL2005的新功能,提供了一种比残缺页检测强大的机制检测IO方面的损坏.以下是详细描述: 页面 C ...
随机推荐
- Scope 安装和使用
Scope 安装和使用 一.安装 1. 软件下载 https://sourceforge.net/projects/cscope/files/ 2. 解压 3. 安装 ./configure --pr ...
- Mac安装ctags
Mac安装ctags mac 系统有自带的ctags,但是不支持"ctags -R"指令,需要自己在安装Exuberant Ctags 1.下载ctags 2. 安装 ./conf ...
- Android开发:在布局里移动ImageView控件
在做一个app时碰到需要移动一个图案的位置,查了一上午资料都没找到demo,自己写一个吧 RelativeLayout.LayoutParams lp = new RelativeLayout.Lay ...
- response 下载文件
String basePath = "D://test.json"; String filename = basePath.substring(basePath.lastIndex ...
- jquery 源码解析 节点遍历
jquery遍历,用于根据其相对于其他元素的关系来查找或选取html元素,以某项选择开始,并沿着这个选择移动,知道移动被称为对dom进行遍历 ☑ <div> 元素是 <ul> ...
- thinkjs中自定义sql语句
一直以为在使用thinkjs时,只能是它自带的sql语句查询,当遇到类似于这样的sql语句时,却不知道这该怎样来写程序,殊不知原来thinkjs可以执行自定义sql语句 SELECT * from a ...
- js面向对象的封装方法,【案例】
封装方法: /** * @矩形canvas库 * @authors Shimily (275766400@qq.com) * @date 2016-12-28 10:30:51 * @version ...
- CentOS 7 Mysql yum源
CentOS 7 安装Mysqlrpm -ivh http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpmyum install m ...
- expdp/impdp
1.c:\>sqlplus user1/password@db2.sql>create directory dmpdp as 'C:\data';本地创建文件夹,然后dmp文件放到这个文件 ...
- 如何在Linux服务器中隐藏PHP版本
通常,大多数默认设置安装的web服务器存在信息泄露,这其中之一就是PHP.PHP 是如今流行的服务端html嵌入式语言(之一?).在如今这个充满挑战的时代,有许多攻击者会尝试发现你服务端的漏洞.因此, ...