树形结构的表,怎么根据一个节点,查出他的上下级。

马猴烧酒123 2019-10-21 08:10:42


create table [ceshi]
(id int, parentid int, code nvarchar(50))

insert into [ceshi]
select 1,0,'a' union all
select 2,1,'b' union all
select 3,1,'c' union all
select 4,2,'d' union all
select 5,2,'e' union all
select 6,2,'f' union all
select 7,3,'g' union all
select 8,3,'h' union all
select 9,4,'i' union all
select 10,5,'j' union all
select 11,9,'k' union all
select 12,7,'l' union all
select 13,7,'m' union all
select 14,8,'n' union all
select 15,13,'o' union all
select 16,14,'p'



差不多就是这样的数据
p_id就是上级节点
我有了G的id 应该查出A,C,G,L,M,O
有C的id 应该查出A,C,G,L,M,O,H,N,P.

这应该怎么查询。
用 WITH AS 么
有上万条数据的话。
会不会慢。
求教。

...全文
618 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
leo_lesley 2019-10-22
  • 打赏
  • 举报
回复

--   试试这个

/*
create table [ceshi](id int, parentid int, code nvarchar(50))
go

insert into [ceshi]
  select 1,0,'a' union all
  select 2,1,'b' union all
  select 3,1,'c' union all
  select 4,2,'d' union all
  select 5,2,'e' union all
  select 6,2,'f' union all
  select 7,3,'g' union all
  select 8,3,'h' union all
  select 9,4,'i' union all
  select 10,5,'j' union all
  select 11,9,'k' union all
  select 12,7,'l' union all
  select 13,7,'m' union all
  select 14,8,'n' union all
  select 15,13,'o' union all
  select 16,14,'p'
 */

 go

--	查找条件
declare @s varchar(100) = 'g'

-- 获取父节点和子节点的数据
;with ParentCode as(
	select id,parentid,code from ceshi where code = @s
	union all
	select a.id,a.parentid,a.code from ceshi a join ParentCode d on a.id = d.parentid
),ChildCode as (
	select id,parentid,code from ceshi where code = @s
	union all
	select a.id,a.parentid,a.code from ceshi a join ChildCode c on a.parentid = c.id
)
/*
--显示数据
select * from (
select * from ParentCode 
union 
select * from ChildCode
) t
*/
--合并字符串
select stuff((select ','+ code
from (
	select * from ParentCode 
	union 
	select * from ChildCode
) t
for xml path('')) , 1,1,'')
leo_lesley 2019-10-21
  • 打赏
  • 举报
回复
引用 1 楼 马猴烧酒123 的回复:
create table [ceshi] (id int, parentid int, code nvarchar(50),longcode (200)) insert into [ceshi] select 1,0,'a','1' union all select 2,1,'b','1.2' union all select 3,1,'c','1.3' union all select 4,2,'d','1.2.4' union all select 5,2,'e','1.2.5' union all select 6,2,'f','1.2.6' union all select 7,3,'g','1.3.7' union all select 8,3,'h','1.3.8' union all select 9,4,'i','1.2.4.9' union all select 10,5,'j','1.2.5.10' union all select 11,9,'k','1.2.4.9.11' union all select 12,7,'l','1.3.7.12' union all select 13,7,'m','1.3.7.13' union all select 14,8,'n','1.3.8.14' union all select 15,13,'o','1.3.7.13.15' union all select 16,14,'p','1.3.8.14.15' 加一列长代码,存他的上下级ID,这样查是不是更方便。
你这种设计且不说符不符合范式的要求,但看这个结果集就没有实际意义,你在查询的时候肯定不是要显示这个ID串,而是要转化成对应的值,这个转化的过程也是耗时的,其次,这一条线上的数据只要有一个发生变化,关联的信息都需要进行更新,比如中间增加一个节点,对应这条线上的路线都需要更新。
Hello World, 2019-10-21
  • 打赏
  • 举报
回复
上万条数据用CET语句不会慢的,加一列路径查下级倒是方便,查上级好像没多大用,不如都用CET解决
马猴烧酒123 2019-10-21
  • 打赏
  • 举报
回复
create table [ceshi] (id int, parentid int, code nvarchar(50),longcode (200)) insert into [ceshi] select 1,0,'a','1' union all select 2,1,'b','1.2' union all select 3,1,'c','1.3' union all select 4,2,'d','1.2.4' union all select 5,2,'e','1.2.5' union all select 6,2,'f','1.2.6' union all select 7,3,'g','1.3.7' union all select 8,3,'h','1.3.8' union all select 9,4,'i','1.2.4.9' union all select 10,5,'j','1.2.5.10' union all select 11,9,'k','1.2.4.9.11' union all select 12,7,'l','1.3.7.12' union all select 13,7,'m','1.3.7.13' union all select 14,8,'n','1.3.8.14' union all select 15,13,'o','1.3.7.13.15' union all select 16,14,'p','1.3.8.14.15' 加一列长代码,存他的上下级ID,这样查是不是更方便。
马猴烧酒123 2019-10-21
  • 打赏
  • 举报
回复
RETURNS @t_level TABLE ( id UNIQUEIDENTIFIER ) AS BEGIN DECLARE @aaa TABLE ( sid UNIQUEIDENTIFIER ); ;WITH CTET AS ( SELECT * FROM dbo.emp_pm_td_classification WHERE exists ( select sid from @aaa s WHERE emp_pm_td_classification.sid =s.sid ) UNION ALL SELECT a.* FROM dbo.emp_pm_td_classification AS a INNER JOIN CTET AS b ON b.sid=a.parentid) insert into @t_level SELECT sid FROM CTET ;with t as (select sid,parentid from emp_pm_td_classification where exists ( select sid from @aaa s WHERE emp_pm_td_classification.sid =s.sid ) union all select b.sid,b.parentid from t a inner join emp_pm_td_classification b on a.parentid=b.sid) insert into @t_level select sid from t @aaa 是查询出来的 临时 表, 大概有130条数据。 单执行往@aaa 插数据 , 执行0秒 。 最终查询结果。4500条左右。执行4秒。 emp_pm_td_classification 总数据,五六千条。
马猴烧酒123 2019-10-21
  • 打赏
  • 举报
回复
引用 3 楼 leo_lesley 的回复:
[quote=引用 1 楼 马猴烧酒123 的回复:] create table [ceshi] (id int, parentid int, code nvarchar(50),longcode (200)) insert into [ceshi] select 1,0,'a','1' union all select 2,1,'b','1.2' union all select 3,1,'c','1.3' union all select 4,2,'d','1.2.4' union all select 5,2,'e','1.2.5' union all select 6,2,'f','1.2.6' union all select 7,3,'g','1.3.7' union all select 8,3,'h','1.3.8' union all select 9,4,'i','1.2.4.9' union all select 10,5,'j','1.2.5.10' union all select 11,9,'k','1.2.4.9.11' union all select 12,7,'l','1.3.7.12' union all select 13,7,'m','1.3.7.13' union all select 14,8,'n','1.3.8.14' union all select 15,13,'o','1.3.7.13.15' union all select 16,14,'p','1.3.8.14.15' 加一列长代码,存他的上下级ID,这样查是不是更方便。
你这种设计且不说符不符合范式的要求,但看这个结果集就没有实际意义,你在查询的时候肯定不是要显示这个ID串,而是要转化成对应的值,这个转化的过程也是耗时的,其次,这一条线上的数据只要有一个发生变化,关联的信息都需要进行更新,比如中间增加一个节点,对应这条线上的路线都需要更新。[/quote] 我现在要坐一个关于菜单权限相关的功能。 菜单就是这样的结构。 分权限,我觉得..我设计的没问题。现在就是查询。。我写的SQL太慢了。

27,579

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 应用实例
社区管理员
  • 应用实例社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧