求一树形取数据的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分送上,不够再加
...全文
717 37 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
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该怎么写?
加载更多回复(17)

22,301

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 疑难问题
社区管理员
  • 疑难问题社区
  • 尘觉
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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