sql语句如何能实现这样的数据显示。
表结构:   表名:   classes   
 id   主键唯一值 
 pid   父级id 
 name   名称   
 这是表数据 
 29	0	一级类别名a 
 30	29	二级类别a 
 31	29	二级类别b 
 32	30	三级类别a 
 33                     30                        三级类别b 
 34                     0                        一级类别名b   
 页面上实现的数据格式如下:   
 一级类别名a 
          二级类别a 
          二级类别b 
                      三级类别a 
 一级类别b 
------解决方案--------------------描述:讨论如何处理树形数据,排序,新增,修改,复制,删除,数据完整性检查,汇总统计     
 表结构描述及数据环境:     
          表名tb,如果修改表名,则相应修改所有数据处理中涉及到的表名tb     
          id为编号(标识字段+主键),pid为上级编号,name为名称,后面可以自行增加其他字段.     
          凡是未特殊标注的地方,对自行增加的字段不影响处理结果/*--数据测试环境 
  表名tb,如果修改表名,则相应修改所有数据处理中涉及到的表名tb 
  id为编号(标识字段+主键) 
  pid为上级编号 
  name为名称,后面可以自行增加其他字段.   
  凡是未特殊标注的地方,对自行增加的字段不影响处理结果     
 --表环境   
 create table tb(id int identity(1,1) not null constraint PK_tb primary key clustered 
  ,pid int,name varchar(20)) 
 insert into tb 
  select 0, '中国 ' 
  union all select 0, '美国 ' 
  union all select 0, '加拿大 ' 
  union all select 1, '北京 ' 
  union all select 1, '上海 ' 
  union all select 1, '江苏 ' 
  union all select 6, '苏州 ' 
  union all select 7, '常熟 ' 
  union all select 6, '南京 ' 
  union all select 6, '无锡 ' 
  union all select 2, '纽约 ' 
  union all select 2, '旧金山 ' 
 go     
 --处理中需要使用的函数及存储过程   
 --1.自定义函数--获取编码累计 
 create function f_getmergid(@id int) 
 returns varchar(8000) 
 as 
 begin 
  declare @re varchar(8000),@pid int   
  --为了数字排序正常,需要统一编码宽度 
  declare @idlen int,@idheader varchar(20) 
  select @idlen=max(len(id)) 
   ,@idheader=space(@idlen) 
  from tb   
  --得到编码累计 
  set @re=right(@idheader+cast(@id as varchar),@idlen) 
  select @pid=pid from tb where id=@id 
  while @@rowcount> 0 
   select @re=right(@idheader+cast(@pid as varchar),@idlen)+ ', '+@re 
    ,@pid=pid from tb where id=@pid 
  return(@re) 
 end 
 go     
 --2.自定义函数--检测某个编码出发,是否被循环引用 
 create function f_chkid(@id int) 
 returns bit --循环,返回1,否则返回0 
 as 
 begin 
  declare @re bit,@pid int    
  set @re=0   
  --检测 
  select @pid=pid from tb where id=@id 
  while @@rowcount> 0 
  begin 
   if @pid=@id 
   begin 
    set @re=1 
    goto lbErr 
   end 
   select @pid=pid from tb where id=@pid 
  end   
 lbErr: 
  return(@re) 
 end 
 go   
 /*--数据复制   
  如果表中包含自定义字段,需要修改存储过程 
  存在嵌套不超过32层的问题. 
 --*/   
 --3.复制指定结点下的子结点到另一个结点下 
 create proc p_copy 
 @s_id int, --复制该项下的所有子项 
 @d_id int, --复制到此项下 
 @new_id int --新增加项的开始编号 
 as 
 declare @nid int,@oid int,@name varchar(20) 
 select id,name into #temp from tb where pid=@s_id and id <@new_id 
 while exists(select 1 from #temp) 
 begin 
  select @oid=id,@name=name from #temp 
  insert into tb values(@d_id,@name) 
  set @nid=@@identity 
  exec p_copy @oid,@nid,@new_id 
  delete from #temp where id=@oid 
 end 
 go   
 --4.批量复制的存储过程--复制指定结点及其下面的所有子结点,并生成新结点 
 create proc p_copystr 
 @s_id varchar(8000) --要复制项的列表,用逗号分隔 
 as 
 declare @nid int,@oid int,@name var