一道 SQL 题 ... (关于树型结构的在关系表中的存储及其应用处理)

相关讨论连接:
http://expert.csdn.net/Expert/TopicView1.asp?id=1477009
原题:
表:
Tree (ID [Integer],ParentID [Integer],Remark [varchar])

INSERT INTO Tree (ID,ParentID)
       SELECT 1,0
    UNION ALL
       SELECT 2,1
    UNION ALL
       SELECT 3,1
    UNION ALL
       SELECT 4,2
    UNION ALL
       SELECT 5,4
    UNION ALL
       SELECT 6,5
    UNION ALL
       SELECT 7,2

T(F1,......)
 INSERT INTO T (F1)
       SELECT 1
    UNION ALL
       SELECT 5
    UNION ALL
       SELECT 3
    UNION ALL
       SELECT 4
    UNION ALL
       SELECT 1
    UNION ALL
       SELECT 7
    UNION ALL
       SELECT 6
    UNION ALL
       SELECT 4
    UNION ALL
       SELECT 5
    UNION ALL
       SELECT 3
    UNION ALL
       SELECT 4
    UNION ALL
       SELECT 1
    UNION ALL
       SELECT 7
    UNION ALL
       SELECT 6
    UNION ALL
       SELECT 4


参考 Tree 表中的父子关系,"祖先"的记录数要包括所有"后代"的记录数,统计 T 表中 F1 各个取值的记录数
ID      Counts
1       15
2       10
3       2
4       8
5       4
6       2
7       2


答案及简单分析:

/*
看了前几个人的答案,似乎都把问题想复杂了"游标"、"临时表"、"递归"。
"游标"、"临时表" 完全可以不用!
"递归" 思想当然应是解决树型结构的该想到的方法!
但是 T-SQL 的嵌套层次最多只能到 32!
icevi(按钮工厂) 的建议是非常值得提倡的,尽管 ID,ParentID 对于仅存储是足够经济的,
但是若用其提供表现形式,性能的确不会太好!
许多高效的树型结构论坛也确实是存储并维护各个节点的层次信息的数据,这样
显示起来仅需一条 SQL 即可!
下面是我的参考答案,两个自定义函数功能几乎一样,都是运算出前面所提的,
应最好主动维护的"层次信息":

方法一: UDF 递归实现! 有 32 层嵌套限制
*/

alter  FUNCTION dbo.Get32Ancestors
(@X integer)
RETURNS VARCHAR(250)
AS
BEGIN
DECLARE @ID integer
DECLARE @ReturnValue VARCHAR(250)

SELECT TOP 1 @ID = ParentID
FROM tree
WHERE [id] = @X

IF @ID <> @X
   BEGIN
     SELECT @ReturnValue  = cast(ISNULL(dbo.Get32Ancestors(@ID),'') as varchar) + '-'+ cast(@X as varchar)
   END
ELSE SET @ReturnValue = @ID

RETURN @ReturnValue
END

go
/*
2003-3-5
方法二: 无任何限制,若层次太深,效率当然不会高(好像也没更好的办法)
改进了一下:
1.正常节点均从0显示! 0-1-3

2.断码 显示 -7-8-9-10
3.GetAllAncestors(不存在的节点)返回NULL
4.GetAllAncestors(根节点)返回 0-自己
5.死循环点显示: 4-5-6-4-8

*/

alter function GetAllAncestors (@X integer)
returns varchar(1000)
as
begin
declare @ReturnValue  varchar(1000)
declare @ID integer
declare @ParentID integer

set @ID = -1

select top 1 @ID=isnull([ID],0),@ParentID = isnull([ParentID],0)
from tree
where ID = @X

while @id <> @parentid and @parentid <> 0 and @ID >0
      and '-' + isnull(@ReturnValue,'') +'-' not like '%-' + cast(@id as varchar) + '-%'
  begin
    if  @ReturnValue is not null
        set @ReturnValue = '-' + @ReturnValue
    set @ReturnValue= cast(@id as varchar) + isnull(@ReturnValue,'')
    set @id = -1
    select top 1 @ID=isnull([ID],0),@ParentID = isnull([ParentID],0)
      from tree
     where ID = @parentid
  end

set @ReturnValue = '-' + @ReturnValue

if @id>0
   set @ReturnValue = cast(@id as varchar) + isnull(@ReturnValue,'')

if @parentid =0 or  @id = @parentid
   set @ReturnValue = '0-'  + isnull(@ReturnValue,'')  

return(@ReturnValue)
--select dbo.GetAllAncestors(10)
end


go

/*
方法一是"高手"的惯性思维把简单的问题搞复杂了,"太累"!
方法二是思路简单清晰,不但是"菜鸟"首选,"高手"也应反思!

若是本题分为两问:
1.求各节点层次信息
2.求属各节点含后代的记录数

可能大家就会受到一些启发!
函数定义完,下面就应该和 icevi(按钮工厂) 同志的答案异曲同工、不谋而和了
*/

select id,dbo.GetAllAncestors(id)
       ,(select count(*)
           from T
          where '-' + dbo.GetAllAncestors(f1) + '-' like '%-' + cast(tree.id as varchar) + '-%')
from tree

select id,dbo.Get32Ancestors(id)
       ,(select count(*)
           from T
          where '-' + dbo.Get32Ancestors(f1) + '-' like '%-' + cast(tree.id as varchar) + '-%')
from tree

/*
另外还要说一下封装的程度的问题,具体情况具体分析,
本题就不适合定义函数直接得到最终结果!
以上答案仅供参考!!
欢迎继续参与讨论!
*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
网络拓扑结构指的是计算机网络中各个节点之间物理连接的方式和形式。常见的网络拓扑结构有星型、总线型、环型、树型、网状型等。 网络拓扑结构的特点包括: 1. 星型结构:适用于小规模的网络,具有简单的物理结构和易于维护的特点,但是对中心节点依赖性较大。 2. 总线型结构:适用于小型局域网,具有低成本和易于扩展的特点,但是当主干线路出现故障时,整个网络会瘫痪。 3. 环型结构:适用于小型局域网,具有成本低廉、易于维护的特点,但是对于大型网络来说,环型结构可能会导致网络拥塞。 4. 树型结构:适用于较大的局域网和广域网,具有高效的数据传输和良好的灵活性,但是节点之间的层次结构较为固定,不太适合需要频繁变更的网络。 5. 网状型结构:适用于大型的分布式系统,具有高度可靠性和灵活性,但是复杂度较高,需要较高的成本和维护费用。 在局域网中,常见的应用情况包括: 1. 星型结构:适用于小型局域网,例如家庭网络或小型办公室网络。 2. 总线型结构:适用于小型局域网,例如小型企业或学校的网络。 3. 环型结构:适用于小型局域网,例如学校或企业内部的局域网。 4. 树型结构:适用于中等规模的局域网或广域网,例如大型企业或学校的网络。 5. 网状型结构:适用于大型的分布式系统,例如互联网或大型数据中心。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

playyuer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值