这个语句怎么写??
表结构如下:
ID(自动加1) parentID(父ID) depth(深度) name(名称) index(排序)
假设有数据如下:
1,0,1,层1,1
2,1,2,层11,1
3,1,2,层12,2
4,0,1,层2,1
5,2,2,层21,1
要求先按父ID分组,取出ID及名称,名称缩进显示,按Index升序排序
即以上数据应显示
1 -层1
2 --层11
3 --层12
4 -层2
5 --层21
这问可不可以只用一个语句写出来呢???
问题点数:100、回复次数:22Top
1 楼FutureSa(异想天开(Haiwer))回复于 2003-09-03 16:03:44 得分 10
只适用于2层:
select a.* from tablename a left join tablename b
on a.parentID=b.id
order by isnull(b.index*1000+a.index,a.index*1000)
Top
2 楼tj_dns(愉快的登山者)回复于 2003-09-03 16:04:58 得分 10
表数据是否应该为:
1,0,1,层1,1
2,1,2,层11,1
3,1,2,层12,2
4,0,1,层2,2
5,4,2,层21,1
才正确?Top
3 楼CrazyFor(冬眠的鼹鼠)回复于 2003-09-03 16:06:04 得分 10
http://expert.csdn.net/Expert/topic/1375/1375432.xml?temp=.8570978
参考当中的排序函数,深度可以有返回的字符串中的逗号数来确定.Top
4 楼superrg(秀华)回复于 2003-09-03 16:06:28 得分 0
to FutureSa(异想天开(Haiwer)):
至少需要实现五层,你的只适用于2层是因为*1000的缘故吗???Top
5 楼pengdali()回复于 2003-09-03 16:09:07 得分 10
select id,REPLICATE('-',depth)+[name] from 你的表Top
6 楼superrg(秀华)回复于 2003-09-03 16:13:52 得分 0
to tj_dns(愉快的登山者):
是的,你看得很仔细,层2的序号应该为2,如果为1则两种结果都是正确的,即原结果以及下面的结果均正确:
4 -层2
5 --层21
1 -层1
2 --层11
3 --层12
to CrazyFor(蚂蚁):
你提供的的确是好东东,里面嵌了一个自定义函数,如果要考虑兼容Access或Sql97,这种做法可能不太可行,我希望的是直接不调用任何自定义函数,游标等直接写出来,有办法吗???
Top
7 楼superrg(秀华)回复于 2003-09-03 16:15:15 得分 0
to pengdali(大力 V2.0):
你的缺少排序,要是我的数据是乱序输入的,你的结果就不是我期待的了~~~~Top
8 楼txlicenhe(马可)回复于 2003-09-03 16:17:50 得分 10
一句写不出多层的吧?Top
9 楼superrg(秀华)回复于 2003-09-03 16:23:01 得分 0
to txlicenhe(马可@李):
希望有高手可以通过几个自连接、外连接把它拿下来,呵呵~~~Top
10 楼yujohny(踏网无痕)回复于 2003-09-03 16:28:56 得分 10
CREATE TABLE #aa(ID INT IDENTITY(1,1),
parentID INT,
depth INT,name NVARCHAR(20),[index] INT)
INSERT INTO #aa VALUES(0,1,'层1',1)
INSERT INTO #aa VALUES(1,2,'层11',1)
INSERT INTO #aa VALUES(1,2,'层12',2)
INSERT INTO #aa VALUES(0,1,'层2',1)
INSERT INTO #aa VALUES(4,2,'层21',1)
select ID,LEFT('----------------',depth)+[name] from #aa
ORDER BY LEFT(name,2),[index]
DROP TABLE #aaTop
11 楼yujohny(踏网无痕)回复于 2003-09-03 16:29:48 得分 0
测试结果
1 -层1
2 --层11
3 --层12
4 -层2
5 --层21
Top
12 楼superrg(秀华)回复于 2003-09-03 16:47:28 得分 0
to yujohny(踏网无痕):
晕,你没有理解我的意思,假如我的name的测试数据不是这样或者为空,你的程序就报错了,再仔细看看我的问题,呵Top
13 楼superrg(秀华)回复于 2003-09-03 17:03:00 得分 0
我想到了一个实现的思路,而且是比较简单的,不过在不用自定义函数或临时表的情况下就不知道该如何实现了,思路如下:
需要排序的计算列是这样得到的:
从第一层开始,排序的顺序为asc(序号),
以下各层是父层的排序值+asc(序号),
这样排序就绝对不会错了,思路也很清晰,不过如何实现就不好做了,前提:
不能用自定义函数,不能用临时表,不能在表中添加字段保存该值,有办法实现吗???Top
14 楼superrg(秀华)回复于 2003-09-03 17:03:44 得分 0
我想到了一个实现的思路,而且是比较简单的,不过在不用自定义函数或临时表的情况下就不知道该如何实现了,思路如下:
需要排序的计算列是这样得到的:
从第一层开始,排序的顺序为asc(序号),
以下各层是父层的排序值+asc(序号),
这样排序就绝对不会错了,思路也很清晰,不过如何实现就不好做了,前提:
不能用自定义函数,不能用临时表,不能在表中添加字段保存该值,有办法实现吗???Top
15 楼FutureSa(异想天开(Haiwer))回复于 2003-09-03 17:04:48 得分 0
多层(支持6层,要求每个节点的子节点不多于1000个,如果能保证每个节点的子节点更少,可以修改C1000函数以达到支持更多层):
create table test0112(
ID int,
parentID int,
depth int,
name varchar(100),
[index] int
)
go
insert test0112
select
1,0,1,'a1',1
union all
select
2,1,2,'a11',1
union all
select
3,1,2,'a12',2
union all
select
4,0,1,'b2',2
union all
select
5,4,2,'b21',1
union all
select
6,3,3,'a121',1
go
create function C1000(@depth int)
returns bigint
as
begin
declare @r bigint
declare @i int
set @i=@depth
set @r=1
while @i>0
begin
set @r=@r*1000
set @i=@i-1
end
return @r
end
go
create function GetIndex(@Id int)
returns bigint
as
begin
declare @r bigint
declare @parentID int
declare @depth int
declare @Index int
declare @Maxdepth int
declare @i int
select @Maxdepth=max(depth) from test0112
select @parentID=parentID,@depth=@Maxdepth-depth,@Index=[Index] from test0112 where id=@id
if isnull(@parentID,0)=0
set @r=dbo.C1000(@depth)*@Index
else
set @r=dbo.C1000(@depth)*@Index+dbo.GetIndex(@parentID)
return @r
end
go
调用:
select id,REPLICATE('-',depth)+name from test0112
order by dbo.GetIndex(id)
结果:
id
----------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1 -a1
2 --a11
3 --a12
6 ---a121
4 -b2
5 --b21
(所影响的行数为 6 行)
Top
16 楼FutureSa(异想天开(Haiwer))回复于 2003-09-03 17:07:55 得分 10
多层不用函数和临时表不好实现,因为这里有个第归的过程
Top
17 楼superrg(秀华)回复于 2003-09-03 17:12:21 得分 0
to FutureSa(异想天开(Haiwer)):
呵
没有办法了,因为要兼容Access和Ms Sql 97版本呀~~~
要是建这么个函数或修改表结构,倒不如增加一个排序字段来得快了Top
18 楼FutureSa(异想天开(Haiwer))回复于 2003-09-03 17:19:01 得分 10
试试:
select a.id,REPLICATE('-',a.depth)+a.name from test0112 a
left join test0112 b
on a.parentID=b.id
left join test0112 c
on b.parentID=c.id
left join test0112 d
on c.parentID=d.id
left join test0112 e
on b.parentID=e.id
order by
isnull(e.[index],isnull(d.[index],isnull(c.[index],isnull(b.[index],isnull(a.[index],0)))))
在现有数据是对的。
Top
19 楼FutureSa(异想天开(Haiwer))回复于 2003-09-03 17:20:12 得分 10
access可以把isnull函数改成iif函数
Top
20 楼superrg(秀华)回复于 2003-09-03 17:26:40 得分 0
to FutureSa(异想天开(Haiwer)):
好像在sql上可以,但在access上没有REPLICATE函数哦Top
21 楼superrg(秀华)回复于 2003-09-03 17:29:38 得分 0
to FutureSa(异想天开(Haiwer)):
多层的时候好像有问题Top
22 楼FutureSa(异想天开(Haiwer))回复于 2003-09-03 17:33:15 得分 10
以上是最多5层的,再多层就加多几个
left join ...
on ...
order by那里也要加
这个语句效率很低的,实际用要注意
数据很多的情况我没有测试,不知道又没有问题。
Top
23 楼superrg(秀华)回复于 2003-09-03 21:48:16 得分 0
to FutureSa(异想天开(Haiwer)):
仔细分析了,结果跟设想有出入的~~~Top
24 楼superrg(秀华)回复于 2003-09-04 09:59:07 得分 0
看来是没办法了,如果没有其他更好的办法,中午就把分散了,呵Top




