一、场景

有一个数据库表里面存储了一个上下级关系的字段,通过存储这个觉得的上级id。如果要查找所有的上级或者下级就要通过循环每个去查找。如下

id p_id name
1 0 老板
2 1 副总
3 1 副总
4 2 项目总监
5 4 A项目经理
6 4 B项目经理
7 5 A1员工
8 5 A2员工
9 6 B1员工
10 6 B2员工

举例:如果要找所有10号员工的所有上级,就得一步一步循环上去?

二、解决方法

思路采用一个递归方法,先将层级结构用一个字段存储起来
表结构和数据

CREATE TABLE [dbo].[test] (
[id] int NOT NULL ,
[name] varchar(255) NULL ,
[pid] int NULL
)
GO-- ----------------------------
-- Records of test
-- ----------------------------
INSERT INTO [dbo].[test] ([id], [name], [pid]) VALUES (N'1', N'老板', N'0')
GO
GO
INSERT INTO [dbo].[test] ([id], [name], [pid]) VALUES (N'2', N'副总', N'1')
GO
GO
INSERT INTO [dbo].[test] ([id], [name], [pid]) VALUES (N'3', N'副总', N'1')
GO
GO
INSERT INTO [dbo].[test] ([id], [name], [pid]) VALUES (N'4', N'项目总监', N'2')
GO
GO
INSERT INTO [dbo].[test] ([id], [name], [pid]) VALUES (N'5', N'A项目经理', N'4')
GO
GO
INSERT INTO [dbo].[test] ([id], [name], [pid]) VALUES (N'6', N'B项目经理', N'4')
GO
GO
INSERT INTO [dbo].[test] ([id], [name], [pid]) VALUES (N'7', N'A1员工', N'5')
GO
GO
INSERT INTO [dbo].[test] ([id], [name], [pid]) VALUES (N'8', N'A2员工', N'5')
GO
GO
INSERT INTO [dbo].[test] ([id], [name], [pid]) VALUES (N'9', N'B1员工', N'6')
GO
GO
INSERT INTO [dbo].[test] ([id], [name], [pid]) VALUES (N'10', N'B2员工', N'6')
GO
GO

**知识点**with as 是子查询模块,如果不了解可先去查询相关知识点
查询如下
找出所有的下级包括自己

WITH x as (select id,name,pidfrom testwhere id = 5union allselect a.id,a.name,a.pidfrom test Ajoin x B on A.pid = B.ID
)
select id,name,pid from x

结果

找出所有的上级包括自己

WITH x as (select id,name,pidfrom testwhere id = 5union allselect a.id,a.name,a.pidfrom test Ajoin x B on B.pid = A.ID
)
select id,name,pid from x

结果

三、进阶

如果每次查找都去循环查找,那层级多了就会影响性能,可以做如下相应的调整。给他一个标志上下级的关联字段,稍微修改一下表结构即可。
思路 :用一个关联字段去关联上下级,每次增加修改删除的时候才需要排序,适合改动较少,查询较多的上下级表。比如上下级部门,上下级员工,这种查询都会多过修改,增加。
表结构
改变:添加一个上下级关联排序字段px

CREATE TABLE [dbo].[test] (
[id] int NOT NULL ,
[name] varchar(255) COLLATE Chinese_PRC_CI_AS NULL ,
[pid] int NULL ,
CONSTRAINT [PK__test__3213E83F7F60ED59] PRIMARY KEY ([id])
)
ON [PRIMARY]
GO

数据还是一样,只是px为空,由我们写一个更新px函数来更新
存储过程解析
- 第一步
先给所有节点排序,给上序号,并且先排好所有的一级节点

declare @n int
select @n=count(*) from menuif OBJECT_ID('tempdb..#xtest') is not null drop table #xtest
select *,right('0000000000'+cast(row_number()over(order by id)  as varchar(10)),len(@n)) rownum
into #xtest
from test
  • 第二步

这一步是为了找出最大的父节点,作为父节点开始节点关联

    SELECT id,name,pidFROM #xtest AS A  WHERE NOT EXISTS(SELECT * FROM #xtest WHERE id=A.pid) 
  • 第三步
    关联所有的子父节点
;WITH T AS
(  SELECT A.id,A.name,A.pid,CAST(rownum AS varchar(MAX)) AS pxFROM #xtest AS A  WHERE NOT EXISTS(SELECT * FROM #xtest WHERE id=A.pid)  UNION ALL   SELECT A.id,A.name,A.pid, CAST(B.px+CAST(A.rownum AS varchar) AS varchar(MAX))FROM #xtest AS A  JOIN T AS B  ON A.pid=B.id
)
SELECT id,name,pid,px
into #test
FROM T
ORDER BY id
  • 第四步
    更新到表中
update a
SET a.px = b.px
from test a ,#test b
where a.id = b.id

四、进阶答案

ALTER procedure [dbo].[var_update_test_px]
as
BEGIN
declare @n int
select @n=count(*) from testif OBJECT_ID('tempdb..#xtest') is not null drop table #xtest
select *,right('0000000000'+cast(row_number()over(order by id)  as varchar(10)),len(@n)) rownum
into #xtest
from testselect * from #xtestif OBJECT_ID('tempdb..#test') is not null drop table #test
;WITH T AS
(  SELECT A.id,A.name,A.pid,CAST(rownum AS varchar(MAX)) AS pxFROM #xtest AS A  WHERE NOT EXISTS(SELECT * FROM #xtest WHERE id=A.pid)  UNION ALL   SELECT A.id,A.name,A.pid, CAST(B.px+CAST(A.rownum AS varchar) AS varchar(MAX))FROM #xtest AS A  JOIN T AS B  ON A.pid=B.id
)
SELECT id,name,pid,px
into #test
FROM T
ORDER BY idbegin trybegin tranupdate a SET a.px = b.pxfrom test a ,#test bwhere a.id = b.idcommitend trybegin catchrollbackend catchEND

sql server 通过上下级关系字段用递归方法生成上下级层级关联数据字段相关推荐

  1. 到T-SQL DML 三级的阶梯:在SQL server中实现关系模型

    作者: Gregory Larsen, 2017/08/02 (第一次出版: 2011/11/09) 翻译:谢雪妮,许雅莉,赖慧芳,刘琼滨 译文: 系列 该文章是阶梯系列的一部分:T-SQL DML的 ...

  2. SQL Server 安装程序遇到以下错误: 无法生成临时类(result=1)。 error CS1567: 生成 Win32 资源时出错: 另一个程序正在使用此文件,进程无法访问。...

    SQL Server 安装程序遇到以下错误: 无法生成临时类(result=1). error CS1567: 生成 Win32 资源时出错: 另一个程序正在使用此文件,进程无法访问. 如果你装了千牛 ...

  3. 18.sql server横向切分、纵向拆分表、相对平均分配数据、复杂sql语句、数据库存储原理(by-朝夕)

    Database 数据库分库分表 1.横向切分 分库分表案例 需要定义规则来选择表 查询: 规则: 2.纵向拆分表 3.相对平均分配数据 复杂Sql语句 一条Sql语句执行的全过程: 你们觉得数据库是 ...

  4. sql server服务器怎么配置文件,配置 SSAS 以生成内存转储文件 - SQL Server | Microsoft Docs...

    配置 SQL Server Analysis Services 以生成内存转储文件 09/25/2020 本文内容 本文介绍如何将 SQL Server Analysis Services 配置为自动 ...

  5. Sql Server之旅——第六站 为什么都说状态少的字段不能建索引

    我们在学sqlserver的时候,大多教科书和前辈们都说状态少的字段不要建索引,由此带来的开销还不如不建索引,但是这句话有多少人真的知道,或者说有多少人真的对此有比较深刻的理解,而不是听别人道听途说. ...

  6. mysql查询每个表的描述_MS SQL SERVER 读取数据库中每个表的描述/注释以及表中字段/列的字段名,字段类型,字段描述/注释/说明等信息...

    SELECT 表名 = CASE WHEN a.colorder=1 THEN d.name ELSE '' END,表说明 = CASE WHEN a.colorder=1 THEN ISNULL( ...

  7. MS SQL SERVER 读取数据库中每个表的描述/注释以及表中字段/列的字段名,字段类型,字段描述/注释/说明等信息...

    SELECT 表名 = CASE WHEN a.colorder=1 THEN d.nameELSE ''END,表说明 = CASE WHEN a.colorder=1 THEN ISNULL(f. ...

  8. oracle 新增自增字段,SQL server、Oracle中拿到新增列时的自增字段值

    #region 增删改数据访问 /// ///增删改数据访问/// /// 语句 /// 参数 /// public static int EditData(string CommandText, O ...

  9. sql server 中不等于<>、!=忽略了NULL的数据,怎么解决

    当在数据库中执行不等于时 条件<>1  同时会忽略掉null的情况 解决方法: IsNull(字段名,0)<>1 转载于:https://www.cnblogs.com/ac1 ...

最新文章

  1. 小游戏来了 游戏小程序你想知道的这有
  2. Java语言特性运用:各种Java语法特性是怎样被Spring各种版本巧妙运用的?
  3. javaWeb Note1
  4. 安卓逆向_8 --- Android 调试工具 DDMS 和 Monitor ( 去掉 车来了 app 的广告 )
  5. 我的 2018 年终总结
  6. Javascript设计模式之——代理模式
  7. 每日一句20191019
  8. MATLAB通信仿真实例1:无噪声信道下DSB-SC调制解调器
  9. Android网络视频播放器DEMO
  10. SRE-网站可靠性工程
  11. java中linechart用法_Line Chart
  12. 微信小游戏开发实战教程15-关卡编辑器的制作以及关卡分享功能的实现
  13. python抢mac微信红包群_要抢红包?Python来帮你~
  14. NewLife使用心得
  15. ps笔记(从基础开始)
  16. JavaSpring全面总结
  17. 中英互译在线翻译官方版
  18. JAVA计算机毕业设计二手儿童闲置物品交易平台Mybatis+系统+数据库+调试部署
  19. 在自动UNDO管理情况下,如何手工增加undo段
  20. 帧结构和物理资源(RB,PRB,VRB,REG,RBG)

热门文章

  1. Windows 文件保护的注册表设置
  2. JS 定时器setInterval clearInterval 延时器setTimeOut 异步 动画
  3. 女生卧室布置的6种形态 INS风小清新文艺范
  4. 《Real-Time Rendering 4th Edition》读书笔记--简单粗糙翻译 第八章 光和颜色 Light And Color
  5. 取得助工前发表的论文可以用来评中级吗?
  6. 超五类屏蔽双绞线和计算机电缆区别,五类线、六类线、超五类线的定义和区别...
  7. python程序运行按什么键_太惨!学Python方法用错,直接从入门到放弃!
  8. 计算机房灭火器单具基准,灭火器的配置基准(4页)-原创力文档
  9. matplotlib无法正常显示中文与dataframe显示省略号
  10. c# FTP文件上传