求一树形取数据的sql语句,表结构简单清晰,不过sql语句有难度,高手请进,解决问题立即揭帖

lci21 2006-12-22 03:08:14
数据库中存储的数据如下:
id parentid name disorder
A01 A 北京 2
A02 A 河北 3
A03 A 上海 1
A0101 A01 海淀 2
A0102 A01 崇文 1
....

我希望得到如下的结果:
id parentid name disorder
A03 A 上海 1
A01 A 北京 2
A0102 A01 崇文 1
A0101 A01 海淀 2
A02 A 河北 3
...
这个sql该怎么写?
也就是说先按照显示顺序列(disorder)出第一层级的,当前节点如果有下级节点,就继续按照下级节点的显示顺序列出,以此类推。
以前我是通过程序递归实现的,但是这样就需要执行很多个sql语句,哪位高手帮忙看看能否通过sql语句一下子取出来,或者只需要执行几个sql语句,最好sql语句是通用sql,多谢了,100分送上,不够再加
...全文
659 点赞 收藏 37
写回复
37 条回复
fengfeiwuwq 2006年12月25日
最好还是在程序里面递归处理
回复 点赞
laoliu666 2006年12月23日
s
回复 点赞
fionazou 2006年12月23日
你的表数据的父子关系定义的不好,不利于在树上增加节点。建议你的父ID从1开始,依此类推。
回复 点赞
fionazou 2006年12月23日
你的表数据的父子关系定义的不好,不利于在树上增加节点。建议你从的父ID1开始。
回复 点赞
MoDingHua 2006年12月23日
可以实现
下面的方法应该是邹建写的
CREATE TABLE tb(id VARCHAR(10), parentid VARCHAR(10),name VARCHAR(10),disorder INT)
INSERT ta SELECT 'A01' , 'A' , '北京', 2
UNION ALL SELECT 'A02' , 'A' , '河北' , 3
UNION ALL SELECT 'A03' , 'A' , '上海' , 1
UNION ALL SELECT 'A0101', 'A01', '海淀' , 2
UNION ALL SELECT 'A0102', 'A01', '崇文' , 1

--查询指定节点及其所有子节点的函数
CREATE FUNCTION f_Cid(@ID char(3))
RETURNS @t_Level TABLE(ID char(3),Level int)
AS
BEGIN
DECLARE @Level int
SET @Level=1
INSERT @t_Level SELECT @ID,@Level
WHILE @@ROWCOUNT>0
BEGIN
SET @Level=@Level+1
INSERT @t_Level SELECT a.ID,@Level
FROM tb a,@t_Level b
WHERE a.PID=b.ID
AND b.Level=@Level-1
END
RETURN
END
GO

--调用函数查询A01及其所有子节点
SELECT a.*
FROM tb a,f_Cid('A01') b
WHERE a.ID=b.ID order by a.parentid asc,a.disorder asc
回复 点赞
whereisthedog 2006年12月23日
我认为 使用sql语句无法实现 不如考虑一下 stl::map
回复 点赞
良少 2006年12月22日
用程序递归调用
回复 点赞
lci21 2006年12月22日
首先非常感谢各位的回复。
我的disorder字段意义是显示顺序,用户可以修改编辑这个值的,如果把这个值给变了,用户就看不懂了,有没有别的办法实现呢
回复 点赞
fcuandy 2006年12月22日
如9988所言,我也觉得这个还是在增写操作记录时直接把顺序维护也加进去好了.

这样排出来,怎么看都要用循环,递规,函数之类的东西.
回复 点赞
tmc1703 2006年12月22日
楼主我觉得你不必死盯着disorderid的序列啊,如果把disorderid的序列跟ID的序列相一致,那么问题就很简单了.
回复 点赞
fcuandy 2006年12月22日
CREATE TABLE ta(id VARCHAR(10), parentid VARCHAR(10),name VARCHAR(10),disorder INT)
INSERT ta SELECT 'A01' , 'A' , '北京', 2
UNION ALL SELECT 'A02' , 'A' , '河北' , 3
UNION ALL SELECT 'A03' , 'A' , '上海' , 1
UNION ALL SELECT 'A0101', 'A01', '海淀' , 2
UNION ALL SELECT 'A0102', 'A01', '崇文' , 1

SELECT *,LEFT('0'+id+'0000000000000',10) aid,1+(len(id)-1)/2-1 Depth INTO # FROM ta ORDER BY Depth

UPDATE # SET aid=STUFF(
STUFF(
STUFF(
STUFF(
STUFF(aid,3,0,'x')
,6,0,'x'
)
,9,0,'x'
)
,12,0,'x'
),Depth*3,1,disorder)



UPDATE s SET aid=STUFF(s.aid,1,3*s.Depth,LEFT(b.aid,3*s.Depth))
FROM # s
INNER JOIN # b
ON SUBSTRING(b.aid,3*s.Depth,1)='x'
AND s.id LIKE b.id + '%'
AND b.Depth+1=s.Depth
WHERE CHARINDEX('x',LEFT(s.aid,s.Depth*3-1))>0


SELECT * FROM # ORDER BY aid
DROP TABLE #,ta

/*
id parentid name disorder aid Depth
---------- ---------- ---------- ----------- -------------------- -----------
A03 A 上海 1 0A103x00x00x00 1
A01 A 北京 2 0A201x00x00x00 1
A0101 A01 海淀 2 0A201x01x00x00 2
A0102 A01 崇文 1 0A201x02x00x00 2
A02 A 河北 3 0A302x00x00x00 1
*/


我的update写的有点问题,级数增多时,好像没有递规下去,谁有兴趣按这方法改改,我要下班了.
回复 点赞
j9988 2006年12月22日
就是用一个循环,让orderid成为:01 0101 0102
0102 (01--为第一层disorderid 02为第二层disorderid )
回复 点赞
j9988 2006年12月22日
declare @a table(id varchar(20),parentid varchar(20),name varchar(20),disorder int)
insert @A select 'A01','A','北京',2
union all select 'A02','A','河北',3
union all select 'A03','A ','上海',1
union all select 'A0101','A01','海淀',2
union all select 'A0102','A01','崇文',1
union all select 'A010101','A0101','海淀1',2
union all select 'A010102','A0101','海淀1',1

declare @b table(id varchar(20),orderid varchar(50),lev int)

declare @i int
set @i=0

insert @b select id,right('00'+rtrim(disorder),2),0 from @a where parentid='A'
while exists(select 1 from @a A,@b B where A.parentid=B.id and B.lev=@i)
begin
insert @b select A.id,B.orderid+right('00'+rtrim(A.disorder),2),@i+1 from @a A,@b B where A.parentid=B.id and B.lev=@i

set @i=@i+1
end

select A.* from @a A,@b B where A.id=B.id order by B.orderid


id parentidname disorder

A03 A 上海 1
A01 A 北京 2
A0102 A01 崇文 1
A0101 A01 海淀 2
A010102 A0101 海淀1 1
A010101 A0101 海淀1 2
A02 A 河北 3
回复 点赞
lci21 2006年12月22日
关键是你看我的order by disorder,先按照disorder排序了,树结构就没有按照层次排序,都错位了
回复 点赞
lci21 2006年12月22日
显示顺序(disorder)指得是该节点在当前级次下的显示顺序,也就是当前节点的兄弟节点相互的顺序,而级次由父节点来约束
回复 点赞
mingxuan3000 2006年12月22日
我在oracle里试过 可以
回复 点赞
lci21 2006年12月22日
j9988(j9988) 增删改的时候很多,经常会增加新节点,修改节点显示顺序等等
回复 点赞
lci21 2006年12月22日
mingxuan3000(铭轩),非常感谢你的回复,你说的方法我试了,不行,根本没有按照顺序列出来
回复 点赞
j9988 2006年12月22日
id parentid name disorder
A03 A 上海 1
A01 A 北京 2
A0102 A01 崇文 1
A0101 A01 海淀 2
A02 A 河北 3

象这种树形结构的表,平时增\删\改机会很少,但查询肯定相当频繁.
你如果用到disorder,我觉得应该在增\删\改里花点时间麻烦一点.让数据库里的记录直接存储为:

id parentid name disorder
A03 A 上海 1
A01 A 北京 2
A0102 A01 崇文 3
A0101 A01 海淀 4
A02 A 河北 5
回复 点赞
lci21 2006年12月22日
如果用mysql该怎么写?
回复 点赞
发动态
发帖子
疑难问题
创建于2007-09-28

9308

社区成员

12.1w+

社区内容

MS-SQL Server 疑难问题
社区公告
暂无公告