在实际运用中经常会创建这样的结构表Category(Id, ParentId, Name),
特别是用于树形结构时(菜单树,权限树..),
这种表设计自然而然地会用到递归,
若是在程序中进行递归(虽然在程序中递归真的更方便一些),
无论是通过ADO.NET简单sql查找还是ORM属性关联都会执行多次sql语句,
难免会造成一些性能上的损耗,所以干脆使用sql的函数来解决这个问题,用函数返回我们最终需要的结果。

数据准备

CREATE TABLE Region
(
Id INT IDENTITY PRIMARY KEY,
Name NVARCHAR(20),
ParentId INT
);
GO insert into Region(Name,ParentId) values('广东',NULL)
insert into Region(Name,ParentId) values('深圳',1)
insert into Region(Name,ParentId) values('惠州',2)
insert into Region(Name,ParentId) values('罗湖区',2)
insert into Region(Name,ParentId) values('福田区',2)
insert into Region(Name,ParentId) values('龙岗区',2)
insert into Region(Name,ParentId) values('惠阳区',3)
insert into Region(Name,ParentId) values('龙门县',3)
insert into Region(Name,ParentId) values('华强北',5)
insert into Region(Name,ParentId) values('体育馆',5) SELECT * FROM dbo.Region AS R

1.查询父节点的所有子节点

/*
* summary:递归获取所有子节点
*/
CREATE function GetRecursiveChildren
(
@Id int
)
returns @t table(Id int,ParentId int,Name nvarchar(20), [Level] int)
begin
declare @i int
set @i = 1
--根节点,Level = 0
insert into @t select @Id,@id,(select Name from Region where Id = @id),0
--直属子节点,Level = 1
insert into @t select Id,ParentId,Name,@i from Region where ParentId = @Id --如果没有新的值插入,循环结束
while @@rowcount<>0
begin
set @i = @i + 1;
insert into @t
select
a.Id,a.ParentId,a.Name,@i
from
Region a, @t b
where
a.ParentId = b.Id and b.Level = @i - 1
end
return
end
go
--调用函数
select * from GetRecursiveChildren(3)

--CTE(公用表表达式)实现
declare @id int
set @id = 3
;with t as--如果CTE前面有语句,需要用分号隔断
(
select Id, ParentId, Name
from Region
where Id = @id
union all
select r1.Id,r1.ParentId,r1.Name
from Region r1 join t as r2 on r1.ParentId = r2.Id
)
select * from t order by Id

2.根据子节点追溯根节点

create function GetRecursiveParent
(
@Id int
)
returns @t table(Id int,ParentId int,Name nvarchar(20), [Level] int)
as
begin
declare @i int
set @i = 1
--插入末节点,Level = 0
insert into @t select @Id,@id,(select Name from Region where Id = @id),0
--插入末节点的父节点,Level = 1
insert into @t select Id,ParentId,Name,@i from Region
where Id = (select ParentId from Region where Id = @Id)
--如果没有新的值插入,循环结束
while @@rowcount<>0
begin
set @i = @i + 1;
insert into @t
select
a.Id,a.ParentId,a.Name,@i
from
Region a, @t b
where
a.Id = b.ParentId and b.Level = @i - 1
end
return
end
go
--调用函数
select * from GetRecursiveParent(8)
go

3.根据导航数据查询节点

create function GetLevel
(
@Id int
)
returns @level table(IdLevel varchar(100),NameLevel nvarchar(200))
as
begin
declare @IdLevel varchar(100),@NameLevel nvarchar(200),@Name nvarchar(50)
select @IdLevel = cast(@Id as varchar(10))
select @NameLevel = (select Name from Region where Id = @Id) while(exists(select Id,ParentId from Region where Id = (select ParentId from Region where Id = @Id)))
begin
select @Id = Id,@Name = Name from Region where Id = (select ParentId from Region where Id = @Id)
select @IdLevel = cast(@Id as varchar(10)) + '>' + @IdLevel
select @NameLevel = @Name + '>' + @NameLevel
end
insert into @level select @IdLevel,@NameLevel
return
end
go
--调用函数
select * from GetLevel(10)
go

sql父子表结构,常用脚本的更多相关文章

  1. SQL server 表结构转Oracle SQL脚本

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

  2. MS SQL 日常维护管理常用脚本(二)

    监控数据库运行 下面是整理.收集监控数据库运行的一些常用脚本,也是MS SQL 日常维护管理常用脚本(一)的续集,欢迎大家补充.提意见. 查看数据库登录名信息   Code Snippet SELEC ...

  3. SQL Server 一句Sql把表结构全部查询出来

    --一句Sql把表结构全部查询出来 SELECT 表名 = Case When A.colorder=1 Then D.name Else '' End, 表说明 = Case When A.colo ...

  4. sql复制表结构,复制表内容语句

    sql复制表结构,复制表内容语句 select * into b from a where 1<>1 select top 0 * into b from a insert into a ...

  5. 用户中心mysql数据库表结构的脚本

    /* Navicat MySQL Data Transfer Source Server : rm-m5e3xn7k26i026e75o.mysql.rds.aliyuncs.com Source S ...

  6. DB2表结构DDL脚本导出

    db2look是导出DDL语句脚本的命令,以下是对db2look的一个简单介绍. 语法:db2look -d <数据库名> -e -t <表名> -o <文件名>. ...

  7. sql复制表结构及复制表数据

    一.复制表结构 假设我们有一个数据表Person,有Id,FirstName,LastName,Weight,Height5个列,表结构可以参考这一篇.现在我们想创建一个新表叫People,表结构和P ...

  8. sql 查看表结构

    sqlserver 查看表结构 exec sp_help @TableName --得到表信息.字段,索引.constraint. exec sp_pkeys @TableName --得到主键. e ...

  9. 7.使用EXPLAIN 来分析SQL和表结构_1

    explain:查看执行计划 使用explain 关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是如何处理你的SQL语句的 分析你的查询语句或是表结构的性能瓶颈 使用explain 可以获 ...

随机推荐

  1. mobilebone与weiui_example.css 使用问题

    weiui_example.css 原page样式属性opacity设置为0 ... 由于我采取的是使用mobilebone,没按照weui官网的来搞这种效果,所以这里会有冲突,设置为默认即可,即op ...

  2. [NOI2017]游戏

    题目描述 http://www.lydsy.com/JudgeOnline/upload/Noi2017D2.pdf 题解 如果说没有x的话,那么每一局只能有两种选择,可以描述为是/非,每条限制也可以 ...

  3. CF700E E. Cool Slogans

    https://codeforces.com/contest/700/problem/E 题解:https://www.luogu.org/problemnew/solution/CF700E 其实就 ...

  4. 【一本通1248:Dungeon Master&&洛谷UVA532 Dungeon Master】

    若不会广搜转向[广搜] [题目描述] 这题是一个三维的迷宫题目,其中用‘.’表示空地,‘#’表示障碍物,‘S’表示起点,‘E’表示终点,求从起点到终点的最小移动次数,解法和二维的类似,只是在行动时除了 ...

  5. C#面向对象基本概念总结

    快过年了,发一篇自己的复习总结.以下内容均是个人理解,如文章有幸被浏览,如有错误的地方欢迎大家提出,相互学习相互进步! 面向对象三大基本特征:封装,继承,多态 一.类 (对象声明的三种方式:以普通基类 ...

  6. window.location.href 传参中文乱码问题!!!

    不是所有地方都会用Ajax  当你使用window.location.href 来传中文参数的时候 如何避免乱码问题 js 是这样写的    下面代码中  方式 封装编码  参数 username  ...

  7. Java基础--面向对象编程2(封装)

    1.封装的定义: 封装:将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问. 2.  为什么需要封装?封装的作用和含义? 首先思考一个问题:当我们要 ...

  8. SNMP mib文件说明

    MIB file的开始和结束 所有的MIB file的都以DEFINITIONS ::= BEGIN关键字开始,以END结束.我们所有添加的节点均应在此之间. XXX-TEST-MIB DEFINIT ...

  9. [源码分析]Java1.8中StringJoiner的使用以及源码分析

    [源码分析]StringJoiner的使用以及源码分析 StringJoiner是Java里1.8新增的类, 或许有一部分人没有接触过. 所以本文将从使用例子入手, 分析StringJoiner的源码 ...

  10. 【codeforces 983E】NN country

    Description In the NN country, there are n cities, numbered from 1 to n, and n−1 roads, connecting t ...