CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
山寨机中的战斗机! 程序优化工程师到底对IT界有没有贡献
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  MS-SQL Server >  基础类

这个语句怎么写??

楼主superrg(秀华)2003-09-03 15:50:53 在 MS-SQL Server / 基础类 提问

表结构如下:  
  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

相关问题

  • 这个语句怎么写?
  • 这个语句怎么写?
  • 这个语句怎么写?
  • 这个语句怎么写?
  • 这个语句怎么写?
  • 这个语句怎么写?
  • 怎么写这个语句
  • 这个语句怎么写?
  • 这个Sql语句怎么写?
  • 这个sql语句怎么写??谢谢

关键词

  • 函数
  • 排序
  • 语句
  • 节点
  • 数据
  • 自定义
  • futuresa
  • haiwer
  • depth
  • parentid

得分解答快速导航

  • 帖主:superrg
  • FutureSa
  • tj_dns
  • CrazyFor
  • pengdali
  • txlicenhe
  • yujohny
  • FutureSa
  • FutureSa
  • FutureSa
  • FutureSa

相关链接

  • SQL Server类图书

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo