对于SQL Server来说,构建显示一个树形结构不是一件容易的事情,逻辑构造能力不是它的强项。不过也不是说它没有能力干这个事情,只要换一种思维方式就可以理解它的工作原理。

例如,现在有一张表的内容如下:

CategoryNO CategoryName                                       Parent
---------- -------------------------------------------------- ------
0          ROOT                                               NULL
1          .NET                                               0
2          DataBase                                           0
3          Java                                               0
4          Others                                             0
5          WindowsOS                                          0
6          F#                                                 1
7          C#                                                 1
8          WPF                                                1
9          VB.NET                                             1
10         SQL Server                                         2
11         J2SE                                               3
12         批处理                                              5
13         注册表                                              5
14         SliverLight                                        8
15         基本命令                                            12
16         扩展命令                                            12
17         HKLM                                               13
18         HKCU                                               13
19         DIR                                                15
20         COPY                                               15
21         DEL                                                15
22         IE                                                 5
23         LINQ                                               1
24         C++                                                0

它看上去是多么混乱无序,我们希望它能按如下方式显示,也就是所谓的树形结构:

CategoryNO  CategoryName
----------- --------------------
1           .NET               
6               F#             
7               C#              
8               WPF             
14                  SliverLight 
9               VB.NET          
23              LINQ            
2           DataBase            
10              SQL Server     
3           Java                
11              J2SE            
4           Others              
5           WindowsOS           
12              批处理          
15                  基本命令    
19                      DIR     
20                      COPY    
21                      DEL     
16                  扩展命令    
13              注册表         
17                  HKLM        
18                  HKCU       
22              IE            
24          C++

至少这样看上去好多了。现在来看看如何实现这个功能。

首先我们需要一个变量来记录当前进入到树形结构的哪个级别,并把它设置为0,表示第一个级别;以及另一个变量来记录当前在对哪条记录操作。

DECLARE @CategoryNO int, @Level int
SET @Level = 0

然后要建立两张临时表,第一张表用来存储待处理记录,第二张表存储最终的结果。关于它们是如何使用的请继续往下看。

CREATE TABLE #TreeViewTemp
(
 CategoryNO int NOT NULL,
 CategoryName nvarchar(30) NOT NULL,
 Parent int NULL,
 [Level] int NOT NULL
)

CREATE TABLE #TreeViewResult
(
 CategoryNO int NOT NULL,
 CategoryName nvarchar(30) NOT NULL
)

接下来向#TreeViewTemp表中插入第一级别的记录。在这里,ROOT记录表示的是根级别,是所有第一级别的父级,最终结果将不包含该记录。注意#TreeViewTemp表中记录了这些记录的级别。

INSERT #TreeViewTemp
SELECT CategoryNO, CategoryName, Parent, @Level
FROM Category
WHERE Parent = 0

再下来,进入一个循环结构。循环结束的条件是#TreeViewTemp表中不再有记录。接下来的内容都是在循环结构中的,BEGIN和END关键字就不写出来了。

WHILE EXISTS (SELECT CategoryNO FROM #TreeViewTemp)

循环的第一条语句,取出#TreeViewTemp中当前级别的第一条记录,并记录下它的CategoryNO(还记得一开始的@CategoryNO和@Level变量吗?)

SELECT TOP(1) @CategoryNO = CategoryNO
FROM #TreeViewTemp
WHERE [Level] = @Level
ORDER BY CategoryNO

如果取不到记录,也就是说临时表中当前级别的记录不存在,那么令@Level变量的值减一,也就是退回上一级别,并继续下一个循环。

IF @@ROWCOUNT = 0
BEGIN
 SET @Level = @Level - 1
 CONTINUE
END

如果当前级别还有记录,就把这条记录插入到最终结果的表中。插入的时候根据当前级别在名称前面加上空格。

INSERT #TreeViewResult
SELECT CategoryNO, SPACE(4 * @Level) + CategoryName
FROM #TreeViewTemp
WHERE CategoryNO = @CategoryNO

接着找出刚刚那条记录的所有子类别,插入到#TreeViewTemp表中。这里把@Level的值加1再插入到表中,表明这些记录是下一级别的。

INSERT #TreeViewTemp
SELECT CategoryNO, CategoryName, Parent, @Level + 1
FROM Category
WHERE Parent = @CategoryNO

如果这条记录有子类别,那么就使@Level的值加1,进入下一级别。

IF @@ROWCOUNT <> 0
 SET @Level = @Level + 1

循环结构中最后一条语句,把#TreeViewTemp中刚刚处理的那条记录删除。

DELETE #TreeViewTemp
WHERE CategoryNO = @CategoryNO

最后一件事,当然是把最终的结果显示出来了。

SELECT CategoryNO, CategoryName FROM #TreeViewResult

最最后的,把临时表删除。

DROP TABLE #TreeViewTemp
DROP TABLE #TreeViewResult

好了,构建树形结构的基本框架就是这样,可以在这个基础上作些修改以适应不同的需求。

我不知道以上说明是否能让大家明白这个逻辑,甚至我自己也说不清楚,它实在是比较复杂……

这个方法有一个缺点,就是使用了临时表。由于临时表的数据是存储在硬盘中的,所以整个过程的速度会有影响。

在最后把整个过程的代码整合在一起:

Code
DECLARE @CategoryNO int, @Level int
SET @Level = 0

CREATE TABLE #TreeViewTemp
(
 CategoryNO int NOT NULL,
 CategoryName nvarchar(30) NOT NULL,
 Parent int NULL,
 [Level] int NOT NULL
)
CREATE TABLE #TreeViewResult
(
 CategoryNO int NOT NULL,
 CategoryName nvarchar(30) NOT NULL
)

INSERT #TreeViewTemp
SELECT CategoryNO, CategoryName, Parent, @Level
FROM Category
WHERE Parent = 0

WHILE EXISTS (SELECT CategoryNO FROM #TreeViewTemp)
BEGIN

SELECT TOP(1) @CategoryNO = CategoryNO
 FROM #TreeViewTemp
 WHERE [Level] = @Level
 ORDER BY CategoryNO

IF @@ROWCOUNT = 0
 BEGIN
  SET @Level = @Level - 1
  CONTINUE
 END

INSERT #TreeViewResult
 SELECT CategoryNO, SPACE(4 * @Level) + CategoryName
 FROM #TreeViewTemp
 WHERE CategoryNO = @CategoryNO

INSERT #TreeViewTemp
 SELECT CategoryNO, CategoryName, Parent, @Level + 1
 FROM Category
 WHERE Parent = @CategoryNO

IF @@ROWCOUNT <> 0
  SET @Level = @Level + 1
 
 DELETE #TreeViewTemp
 WHERE CategoryNO = @CategoryNO

END

SELECT CategoryNO, CategoryName FROM #TreeViewResult

DROP TABLE #TreeViewTemp
DROP TABLE #TreeViewResult

转载于:https://www.cnblogs.com/zplutor/archive/2009/07/31/1536146.html

[SQL Server]树形结构的创建相关推荐

  1. SQL Server 索引结构及其使用(一)[转]

    SQL Server 索引结构及其使用(一)  作者:freedk 一.深入浅出理解索引结构 实际上,您可以把索引理解为一种特殊的目录.微软的SQL SERVER提供了两种索引:聚集索引(cluste ...

  2. [转]聚集索引和非聚集索引(sql server索引结构及其使用)

    聚集索引和非聚集索引(sql server索引结构及其使用) [来自]http://www.cnblogs.com/xinqqing83/archive/2006/10/31/545747.html ...

  3. SQL Server 索引结构及其使用(四)

    KeyLife富翁笔记 作者: HongYuan 标题: SQL Server 索引结构及其使用(四) 关键字: 分类: 个人专区 密级: 公开 (评分: , 回复: 0, 阅读: 601)  ...

  4. 用sql改oracle表结构,SQL server 表结构转Oracle SQL脚本

    SQL server 表结构转Oracle SQL脚本 /****** Object: StoredProcedure [dbo].[getOracle] Script Date: 2019/7/25 ...

  5. SQL Server数据库结构

    SQL Server数据库结构和管理 数据库物理存储结构 数据库文件和文件组 主数据库文件(Primary Database File):是数据库的起点,可以指向数据库中文件的其它部分.每个数据库都有 ...

  6. 昨日关注:SQL Server 索引结构及其使用

    2005-4-25 [数据库技术] SQL Server 索引结构及其使用(4) # 为解决这个矛盾,笔者后来又添加了一个日期列,其默认值为getdate().用户在写入记录时,这个列自动写入当时的时 ...

  7. SQL Server 索引结构及其使用(二)(转)

    SQL Server 索引结构及其使用(二) 作者:freedk 一.深入浅出理解索引结构 改善SQL语句 很多人不知道SQL语句在SQL SERVER中是如何执行的,他们担心自己所写的SQL语句会被 ...

  8. 【转】SQL Server 索引结构及其使用(二)

    SQL Server 索引结构及其使用(二)  作者:freedk 一.深入浅出理解索引结构 改善SQL语句 很多人不知道SQL语句在SQL SERVER中是如何执行的,他们担心自己所写的SQL语句会 ...

  9. SQL Server 索引结构及其使用(三)(转)

    SQL Server 索引结构及其使用(三) 作者:freedk 一.深入浅出理解索引结构 二.改善SQL语句 实现小数据量和海量数据的通用分页显示存储过程 建立一个 Web 应用,分页浏览功能必不可 ...

最新文章

  1. 如何使用jquery判断一个元素是否含有一个指定的类(class)
  2. C++对C的加强之 “实用性”增加
  3. 台式计算机风扇声音大怎么处理,如何解决电脑电源风扇声音大的问题?
  4. 局域网限制网速软件_大文件传输工具,比微信、QQ文件传输还好用的传输软件,关键还不限速!...
  5. 二叉树+链表+字符串+栈和队列高频面试题合集
  6. (一)Redis初学教程之安装篇
  7. CICD详解(六)——SVN+Jenkins项目控制实战
  8. pandas中DataFrame的修改元素值、缺失值处理、合并操作的方法
  9. 【课程·研】高级人工智能 | MOOC习题及课后作业:期末考试
  10. matlab绘制奈奎图,matlab画奈奎斯特图
  11. SQL语句查询:查询本周过生日的信息
  12. P61-指针-指针和数组
  13. Flarum轻量级论坛的安装
  14. blackjack - pwnable
  15. java过滤微信表情符号_微信隐藏彩蛋!表情加符号就能传递“神秘信息”
  16. 【mud】文字mud游戏的魅力(龟跑比赛)
  17. ASP.Net Core The type initializer for 'Gdip' threw an exception
  18. 5G与AI,共舞“华尔兹”
  19. 如何注册域名?注册域名时要注意些什么?
  20. postman 的一些深度功能

热门文章

  1. git branch 为什么会进入编辑状态_Git很难,搞砸很容易,好在有神奇命令让时光倒流...
  2. python中的位置怎么看_如何知道项目在Python有序字典中的位置
  3. 文字转wav_这6款超良心语音转文字工具,真让人省心!
  4. Apache Web Server - httpd 的长连接配置
  5. 【HDU 1711】Number Sequence(裸KMP算法)
  6. redis 缓存击穿 看一篇成高手系列 三
  7. HMM:Hidden Markov Model 代码讲解
  8. 关于c++ pair自己遇到的一个问题?为何不一样?为何第一个程序不能返回pair内数组的值呢?(已经解决)
  9. UEFI下用rufus安装ubuntu16.04 LTS
  10. 提取一个二进制位最右侧的1