树结构查询

TGZ 2009-08-27 11:22:09
现有表1,结构如下:

层 父ID ID 名称 排序
3 Y T T1 1
1 SYS A A1 2
1 SYS B B1 1
2 B X X1 2
2 A S S1 1
2 B Y Y1 1


要求结果如下:

名称 ID
A1 A
--S1 S
B1 B
--Y1 Y
--T1 T
--X1 X


请问这个能用一个SQL写出来吗?



...全文
98 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
LIHY70 2009-08-27
  • 打赏
  • 举报
回复
学习~
htl258_Tony 2009-08-27
  • 打赏
  • 举报
回复


--> 生成测试数据表:tb

If not object_id('[tb]') is null
Drop table [tb]
Go
Create table [tb]([层] int,[父ID] nvarchar(3),[ID] nvarchar(1),[名称] nvarchar(2),[排序] int)
Insert tb
Select 3,'Y','T','T1',1 union all
Select 1,'SYS','A','A1',2 union all
Select 1,'SYS','B','B1',1 union all
Select 2,'B','X','X1',2 union all
Select 2,'A','S','S1',1 union all
Select 2,'B','Y','Y1',1
Go
--Select * from tb

-->SQL查询如下:
;with t as
(
select cast(ID as varchar(500)) px, * from tb where 层=1
union all
select cast(t.px+'.'+tb.id as varchar(500)), tb.* from tb,t where tb.[父ID]=t.[ID]
)
select case when [层]=1 then 名称 else replicate(' ',层)+replicate('-',层)+名称 end 名称,ID
from t
order by px,排序

/*
名称 ID
A1 A
--S1 S
B1 B
--X1 X
--Y1 Y
---T1 T
*/
jiangshun 2009-08-27
  • 打赏
  • 举报
回复

--> 测试数据:[TB]
if object_id('[TB]') is not null drop table [TB]
create table [TB]([层] int,[父ID] varchar(max),[ID] varchar(max),[名称] varchar(max),[排序] int)
insert [TB]
select 3,'Y','T','T1',1 union all
select 1,'SYS','A','A1',2 union all
select 1,'SYS','B','B1',1 union all
select 2,'B','X','X1',2 union all
select 2,'A','S','S1',1 union all
select 2,'B','Y','Y1',1

;with
l8r as(
select 名称,ID,flag=[ID] from TB where 层=1 union all
select REPLICATE('-',a.层)+a.名称,a.ID,flag=a.[父ID]+a.[ID] from tb a join l8r b on a.[父ID]=b.id
)
select 名称,ID from l8r order by flag

/*
名称 ID
------------------------------------- --------------
A1 A
--S1 S
B1 B
--X1 X
--Y1 Y
---T1 T

(6 行受影响)

*/
drop table TB
zc_0101 2009-08-27
  • 打赏
  • 举报
回复
我只管接分
--小F-- 2009-08-27
  • 打赏
  • 举报
回复
CREATE TABLE BOM(PID INT,ID INT)
INSERT INTO BOM SELECT 801,101
INSERT INTO BOM SELECT 801,102
INSERT INTO BOM SELECT 801,103
INSERT INTO BOM SELECT 801,601
INSERT INTO BOM SELECT 601,101
INSERT INTO BOM SELECT 601,105
INSERT INTO BOM SELECT 601,501
INSERT INTO BOM SELECT 501,106
INSERT INTO BOM SELECT 501,121
GO

CREATE FUNCTION F_GETROOT(@PID INT)
RETURNS INT
AS
BEGIN
DECLARE @ID INT
WHILE EXISTS(SELECT 1 FROM BOM WHERE ID=@PID)
BEGIN
SET @ID=@PID
SELECT @PID=PID FROM BOM WHERE ID=@ID
END
RETURN @PID
END
GO

SELECT PID=DBO.F_GETROOT(PID),ID FROM BOM
GO

/*
PID ID
----------- -----------
801 101
801 102
801 103
801 601
801 101
801 105
801 501
801 106
801 121
*/


DROP FUNCTION F_GETROOT
DROP TABLE BOM
GO




--生成测试数据
create table BOM_1(Item int,bom_head varchar(20),bom_child varchar(20),number int,products_attribute varchar(20))
insert into BOM_1 select 1 ,'A' ,'A1',1,'采购'
insert into BOM_1 select 2 ,'A' ,'A2',2,'生产'
insert into BOM_1 select 3 ,'A2','A3',3,'生产'
insert into BOM_1 select 4 ,'A2','A4',2,'采购'
insert into BOM_1 select 5 ,'A3','A5',2,'采购'
insert into BOM_1 select 6 ,'A3','A6',1,'采购'
insert into BOM_1 select 7 ,'B' ,'B1',1,'采购'
insert into BOM_1 select 8 ,'B' ,'B2',2,'生产'
insert into BOM_1 select 9 ,'B2','B3',3,'生产'
insert into BOM_1 select 10,'B2','B4',2,'采购'
insert into BOM_1 select 11,'B3','B5',2,'采购'
insert into BOM_1 select 12,'B3','B6',2,'采购'
go


--创建用户定义函数,用于取每个父节点下子节点的采购配置信息
create function f_stock(@bom_head varchar(20))
returns @t table(bom varchar(20),number int)
as
begin
declare @level int
declare @a table(bom varchar(20),number int,products_attribute varchar(20),[level] int)
set @level=1

if exists(select 1 from BOM_1 where bom_head=@bom_head)
insert into @a
select bom_child,number,products_attribute,@level
from BOM_1
where bom_head=@bom_head

while exists(select 1 from @a where [level]=@level and products_attribute='生产')
begin
set @level=@level+1
insert into @a(bom,number,products_attribute,[level])
select a.bom_child,a.number,a.products_attribute,@level
from BOM_1 a,@a b
where a.bom_head=b.bom and b.[level]=@level-1
end

insert into @t(bom,number) select bom,number from @a where products_attribute='采购'
return
end
go


--执行调用,取父节点'A'一个标准配置分解的采购信息及数量
select * from dbo.f_stock('A')






--生成测试数据
create table BOM(ID INT,PID INT,MSG VARCHAR(1000))
insert into BOM select 1,0,NULL
insert into BOM select 2,1,NULL
insert into BOM select 3,1,NULL
insert into BOM select 4,2,NULL
insert into BOM select 5,3,NULL
insert into BOM select 6,5,NULL
insert into BOM select 7,6,NULL
go

--创建用户定义函数用于取每个父节点下子节点的采购配置信息
create function f_getChild(@ID VARCHAR(10))
returns @t table(ID VARCHAR(10),PID VARCHAR(10),Level INT)
as
begin
declare @i int
set @i = 1
insert into @t select ID,PID,@i from BOM where PID = @ID

while @@rowcount<>0
begin
set @i = @i + 1

insert into @t
select
a.ID,a.PID,@i
from
BOM a,@t b
where
a.PID=b.ID and b.Level = @i-1
end
return
end
go

--执行查询
select ID from dbo.f_getChild(3)
go

--输出结果
/*
ID
----
5
6
7
*/

--删除测试数据
drop function f_getChild
drop table BOM





创建用户定义函数,每个子节点de父节点的信息


--生成测试数据
create table BOM(ID int,parentID int,sClassName varchar(10))
insert into BOM values(1,0,'1111' )
insert into BOM values(2,1,'1111_1' )
insert into BOM values(3,2,'1111-1-1' )
insert into BOM values(4,3,'1111-1-1-1')
insert into BOM values(5,1,'1111-2' )

go

--创建用户定义函数,每个子节点de父节点的信息
create function f_getParent(@ID int)
returns varchar(40)
as
begin
declare @ret varchar(40)

while exists(select 1 from BOM where ID=@ID and parentID<>0)
begin
select @ID=b.ID,@ret=','+rtrim(b.ID)+isnull(@ret,'')
from
BOM a,BOM b
where
a.ID=@ID and b.ID=a.parentID
end

set @ret=stuff(@ret,1,1,'')
return @ret
end
go

--执行查询
select ID,isnull(dbo.f_getParent(ID),'') as parentID from BOM
go

--输出结果
/*
ID parentID
----------- ----------------------------------------
1
2 1
3 1,2
4 1,2,3
5 1
*/

--删除测试数据
drop function f_getParent
drop table BOM
go

SQL77 2009-08-27
  • 打赏
  • 举报
回复
等TONY哥
jiangshun 2009-08-27
  • 打赏
  • 举报
回复

--测试数据
DECLARE @t TABLE(ID char(3),PID char(3),Name nvarchar(10))
INSERT @t SELECT '001',NULL ,'山东省'
UNION ALL SELECT '002','001','烟台市'
UNION ALL SELECT '004','002','招远市'
UNION ALL SELECT '003','001','青岛市'
UNION ALL SELECT '005',NULL ,'四会市'
UNION ALL SELECT '006','005','清远市'
UNION ALL SELECT '007','006','小分市'

--深度排序显示处理
--生成每个节点的编码累计(相同当单编号法的编码)
DECLARE @t_Level TABLE(ID char(3),Level int,Sort varchar(8000))
DECLARE @Level int
SET @Level=0
INSERT @t_Level SELECT ID,@Level,ID
FROM @t
WHERE PID IS NULL
WHILE @@ROWCOUNT>0
BEGIN
SET @Level=@Level+1
INSERT @t_Level SELECT a.ID,@Level,b.Sort+a.ID
FROM @t a,@t_Level b
WHERE a.PID=b.ID
AND b.Level=@Level-1
END

--显示结果
SELECT SPACE(b.Level*2)+'|--'+a.Name
FROM @t a,@t_Level b
WHERE a.ID=b.ID
ORDER BY b.Sort
/*--结果
|--山东省
|--烟台市
|--招远市
|--青岛市
|--四会市
|--清远市
|--小分市
--*/
guguda2008 2009-08-27
  • 打赏
  • 举报
回复
只能用存儲吧,用一個SQL沒必要,性能肯定不行
tengjian1981 2009-08-27
  • 打赏
  • 举报
回复
可以加一列IDList,记录所有父ID

层 父ID ID 名称 排序 IDList
3 Y T T1 1 SYS,B,Y,T
1 SYS A A1 2 SYS,A
1 SYS B B1 1 SYS,B
2 B X X1 2 SYS,B,X
2 A S S1 1 SYS,A,S
2 B Y Y1 1 SYS,B,Y


然后Order By IDList就可以了,而且这样查某个节点的子孙节点很好查,只要查IDList like '%SYS,B%'就可以查到所有B节点子孙

34,593

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server相关内容讨论专区
社区管理员
  • 基础类社区
  • 二月十六
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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