查询树形节点各结点的路径

*

标题:查询各节点的父路径函数
 
*/
 
/*
原始数据及要求结果如下:
--食品 
  --水果 
    --香蕉 
    --苹果    
  --蔬菜 
    --青菜
id          pid         name                 
----------- ----------- -------------------- 
1           0           食品
2           1           水果
3           1           蔬菜
4           2           香蕉
5           2           苹果
6           3           青菜
 
要求得到各节点的父路径即如下结果:
id  pid name  路径                         
--- --- ----- ---------------
1   0   食品  食品
2   1   水果  食品,水果
3   1   蔬菜  食品,蔬菜
4   2   香蕉  食品,水果,香蕉
5   2   苹果  食品,水果,苹果
6   3   青菜  食品,蔬菜,青菜 
*/
 
create table tb (id int , pid int name nvarchar(20)) 
insert into tb values(1 , 0 , '食品')
insert into tb values(2 , 1 , '水果')
insert into tb values(3 , 1 , '蔬菜')
insert into tb values(4 , 2 , '香蕉')
insert into tb values(5 , 2 , '苹果')
insert into tb values(6 , 3 , '青菜')
go
 
--查询各节点的父路径函数
create function f_pid(@id intreturns varchar(100)
as
begin
  declare @re_str as varchar(100)
  set @re_str = ''
  select @re_str = name from tb where id = @id
  while exists (select from tb where id = @id and pid <> 0)
    begin
      select @id = b.id , @re_str = b.name ',' + @re_str from tb a , tb b where a.id = @id and a.pid = b.id
    end
  return @re_str
end
go
 
select * , dbo.f_pid(id) 路径 from tb order by id
 
drop table tb
drop function f_pid
 
 
/*
标题:查询所有节点及其所有子节点的函数
 
*/
 
--生成测试数据 
create table tb(id varchar(10),pid varchar(10)) 
insert into tb select 'a'null 
insert into tb select 'b''a' 
insert into tb select 'c''a' 
insert into tb select 'd''b' 
insert into tb select 'e''b' 
insert into tb select 'f''c' 
insert into tb select 'g''c' 
go 
 
--创建用户定义函数 
create function f_getchild(@id varchar(10)) returns varchar(8000) 
as 
begin 
  declare @i int , @ret varchar(8000) 
  declare @t table(id varchar(10) , pid varchar(10) , level int
  set @i = 1 
  insert into @t select id , pid , @i from tb where id = @id 
  while @@rowcount <> 0 
  begin 
    set @i = @i + 1 
    insert into @t select a.id , a.pid , @i from tb a , @t b where a.pid = b.id and b.level = @i - 1
  end 
  select @ret = isnull(@ret , '') + id + ',' from @t 
  return left(@ret , len(@ret) - 1)
end 
go 
 
--执行查询 
select id , children = isnull(dbo.f_getchild(id) , ''from tb group by id
go 
 
--输出结果 
/* 
id         children     
---------- -------------
a          a,b,c,d,e,f,g
b          b,d,e
c          c,f,g
d          d
e          e
f          f
g          g
 
(所影响的行数为 7 行)
 
*/ 
 
--删除测试数据 
drop function f_getchild 
drop table tb
 
================================================================
/*
标题:SQL SERVER 2000中查询指定节点及其所有子节点的函数(字符串形式显示)
 
*/
 
--生成测试数据 
create table tb(id varchar(3) , pid varchar(3) , name varchar(10))
insert into tb values('001' null  '广东省')
insert into tb values('002' '001' '广州市')
insert into tb values('003' '001' '深圳市')
insert into tb values('004' '002' '天河区')
insert into tb values('005' '003' '罗湖区')
insert into tb values('006' '003' '福田区')
insert into tb values('007' '003' '宝安区')
insert into tb values('008' '007' '西乡镇')
insert into tb values('009' '007' '龙华镇')
insert into tb values('010' '007' '松岗镇')
go
 
--创建用户定义函数 
create function f_cid(@id varchar(10)) returns varchar(8000) 
as 
begin 
  declare @i int , @ret varchar(8000) 
  declare @t table(id varchar(10) , pid varchar(10) , level int
  set @i = 1 
  insert into @t select id , pid , @i from tb where id = @id 
  while @@rowcount <> 0 
  begin 
    set @i = @i + 1 
    insert into @t select a.id , a.pid , @i from tb a , @t b where a.pid = b.id and b.level = @i - 1
  end 
  select @ret = isnull(@ret , '') + id + ',' from @t 
  return left(@ret , len(@ret) - 1)
end 
go 
 
--执行查询 
select id , children = isnull(dbo.f_cid(id) , ''from tb group by id
 
drop table tb
drop function f_cid
 
/*
id   children                               
---- ---------------------------------------
001  001,002,003,004,005,006,007,008,009,010
002  002,004
003  003,005,006,007,008,009,010
004  004
005  005
006  006
007  007,008,009,010
008  008
009  009
010  010
 
(所影响的行数为 10 行)
*/
 
/*
标题:SQL SERVER 2000中查询指定节点及其所有父节点的函数(字符串形式显示)
 
*/
 
/*
create table tb(id varchar(3) , pid varchar(3) , name varchar(10))
insert into tb values('001' null  '广东省')
insert into tb values('002' '001' '广州市')
insert into tb values('003' '001' '深圳市')
insert into tb values('004' '002' '天河区')
insert into tb values('005' '003' '罗湖区')
insert into tb values('006' '003' '福田区')
insert into tb values('007' '003' '宝安区')
insert into tb values('008' '007' '西乡镇')
insert into tb values('009' '007' '龙华镇')
insert into tb values('010' '007' '松岗镇')
go
 
--查询各节点的父路径函数
create function f_pid(@id varchar(3)) returns varchar(100)
as
begin
  declare @re_str as varchar(100)
  set @re_str = ''
  select @re_str = name from tb where id = @id
  while exists (select from tb where id = @id and pid is not null)
    begin
      select @id = b.id , @re_str = b.name ',' + @re_str from tb a , tb b where a.id = @id and a.pid = b.id
    end
  return @re_str
end
go
 
select * , dbo.f_pid(id) 路径 from tb order by id
 
drop table tb
drop function f_pid
 
/*
id   pid  name       路径                       
---- ---- ---------- ---------------------------
001  NULL 广东省     广东省
002  001  广州市     广东省,广州市
003  001  深圳市     广东省,深圳市
004  002  天河区     广东省,广州市,天河区
005  003  罗湖区     广东省,深圳市,罗湖区
006  003  福田区     广东省,深圳市,福田区
007  003  宝安区     广东省,深圳市,宝安区
008  007  西乡镇     广东省,深圳市,宝安区,西乡镇
009  007  龙华镇     广东省,深圳市,宝安区,龙华镇
010  007  松岗镇     广东省,深圳市,宝安区,松岗镇
 
(所影响的行数为 10 行)
*/
 
==================================================================
id-每个节结点的唯一标识,可以是流水号
Code-本级代码
pid-父节点的id
现在要求写出查询各个结点的select语句!希望各位高手给点建议

code     name  id code pid name
0
01           服装 1 01 0 服装
0101     男装 2 01 1 男装
010101     西装 3 01 2 西装
01010101     全毛 4 01 3 全毛
01010102     化纤 5 02 3 化纤
010102     休闲装 6 02 2 休闲装
0102     女装 7 02 1 女装
010201     套装 8 01 7 套装
010202     职业装 9 02 7 职业装
010203     休闲装 10 03 7 休闲装
010204       西装 11 04 7 西装
01020401     全毛 12 01 11 全毛
01020402     化纤 13 02 11 化纤
010205       休闲装 14 05 7 休闲装
 
 
--------------------------------------------------------------------------
--  Author : htl258(Tony)
--  Date   : 2010-04-23 02:37:24
--  Version:Microsoft SQL Server 2008 (RTM) - 10.0.1600.22 (Intel X86) 
--          Jul  9 2008 14:43:34 
--          Copyright (c) 1988-2008 Microsoft Corporation
--          Developer Edition on Windows NT 5.1 <X86> (Build 2600: Service Pack 3)
--------------------------------------------------------------------------
--> 生成测试数据表:tb
 
IF NOT OBJECT_ID('[tb]'IS NULL
    DROP TABLE [tb]
GO
CREATE TABLE [tb]([id] INT,[code] NVARCHAR(10),[pid] INT,[name] NVARCHAR(10))
INSERT [tb]
SELECT 1,'01',0,N'服装' UNION ALL
SELECT 2,'01',1,N'男装' UNION ALL
SELECT 3,'01',2,N'西装' UNION ALL
SELECT 4,'01',3,N'全毛' UNION ALL
SELECT 5,'02',3,N'化纤' UNION ALL
SELECT 6,'02',2,N'休闲装' UNION ALL
SELECT 7,'02',1,N'女装' UNION ALL
SELECT 8,'01',7,N'套装' UNION ALL
SELECT 9,'02',7,N'职业装' UNION ALL
SELECT 10,'03',7,N'休闲装' UNION ALL
SELECT 11,'04',7,N'西装' UNION ALL
SELECT 12,'01',11,N'全毛' UNION ALL
SELECT 13,'02',11,N'化纤' UNION ALL
SELECT 14,'05',7,N'休闲装'
GO
--SELECT * FROM [tb]
 
-->SQL查询如下:
 
;WITH AS
(
    SELECT CAST(CODE AS VARCHAR(20)) AS CODE,*,
        CAST(ROW_NUMBER() OVER(ORDER BY id) AS VARBINARY(MAX)) AS px 
    FROM tb AS A
    WHERE NOT EXISTS(SELECT FROM tb WHERE id=A.pid)
    UNION ALL 
    SELECT CAST(B.CODE+A.CODE AS VARCHAR(20)),A.*,
         CAST(B.px+CAST(ROW_NUMBER() OVER(PARTITION BY B.pid ORDER BY A.id) AS BINARY(4)) 
               AS VARBINARY(MAX))    
    FROM tb AS A
        JOIN AS B
    ON A.pid=B.id
)
SELECT Code,Name FROM 
ORDER BY px
/*
Code                 Name
-------------------- ----------
01                   服装
0101                 男装
010101               西装
01010101             全毛
01010102             化纤
010102               休闲装
0102                 女装
010201               套装
010202               职业装
010203               休闲装
010204               西装
01020401             全毛
01020402             化纤
010205               休闲装
 
(14 行受影响)
*/
posted @ 2012-11-13 20:20  岁寒松柏  阅读(476)  评论(0编辑  收藏  举报