Tree (ID [Integer]ParentID [Integer]Remark [varchar]) INSERT INTO Tree (IDParentID) SELECT UNION ALL SELECT UNION ALL SELECT UNION ALL SELECT UNION ALL SELECT UNION ALL SELECT UNION ALL SELECT T(F) INSERT INTO T (F) SELECT UNION ALL SELECT UNION ALL SELECT UNION ALL SELECT UNION ALL SELECT UNION ALL SELECT UNION ALL SELECT UNION ALL SELECT UNION ALL SELECT UNION ALL SELECT UNION ALL SELECT UNION ALL SELECT UNION ALL SELECT UNION ALL SELECT UNION ALL SELECT 参考 Tree 表中的父子关系祖先的记录数要包括所有后代的记录数统计 T 表中 F 各个取值的记录数? IDCounts 答案及简单分析: /* 看了前几个人的答案似乎都把问题想复杂了游标临时表递归 游标临时表 完全可以不用! 递归 思想当然应是解决树型结构的该想到的方法! 但是 TSQL 的嵌套层次最多只能到 ! icevi(按钮工厂) 的建议是非常值得提倡的尽管 IDParentID 对于仅存储是足够经济的 但是若用其提供表现形式性能的确不会太好! 许多高效的树型结构论坛也确实是存储并维护各个节点的层次信息的数据这样 显示起来仅需一条 SQL 即可! 下面是我的参考答案两个自定义函数功能几乎一样都是运算出前面所提的 应最好主动维护的层次信息: 方法一: UDF 递归实现! 有 层嵌套限制 */ alterFUNCTION dboGetAncestors (@X integer) RETURNS VARCHAR() AS BEGIN DECLARE @ID integer DECLARE @ReturnValue VARCHAR() SELECT TOP @ID = ParentID FROM tree WHERE [id] = @X IF @ID <> @X BEGIN SELECT @ReturnValue= cast(ISNULL(dboGetAncestors(@ID)) as varchar) + + cast(@X as varchar) END ELSE SET @ReturnValue = @ID RETURN @ReturnValue END go /*
方法二: 无任何限制若层次太深效率当然不会高(好像也没更好的办法) 改进了一下: 正常节点均从显示! 断码 显示 GetAllAncestors(不存在的节点)返回NULL GetAllAncestors(根节点)返回 自己 死循环点显示: */ alter function GetAllAncestors (@X integer) returns varchar() as begin declare @ReturnValuevarchar() declare @ID integer declare @ParentID integer set @ID = select top @ID=isnull([ID])@ParentID = isnull([ParentID]) from tree where ID = @X while @id <> @parentid and @parentid <> and @ID > 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 = select top @ID=isnull([ID])@ParentID = isnull([ParentID]) from tree where ID = @parentid end set @ReturnValue = + @ReturnValue if @id> set @ReturnValue = cast(@id as varchar) + isnull(@ReturnValue) if @parentid = or@id = @parentid set @ReturnValue = + isnull(@ReturnValue) return(@ReturnValue) select dboGetAllAncestors() end go /* 方法一是高手的惯性思维把简单的问题搞复杂了太累! 方法二是思路简单清晰不但是菜鸟首选高手也应反思! 若是本题分为两问: 求各节点层次信息 求属各节点含后代的记录数 可能大家就会受到一些启发! 函数定义完下面就应该和 icevi(按钮工厂) 同志的答案异曲同工不谋而和了 */ select iddboGetAllAncestors(id) (select count(*) from T where + dboGetAllAncestors(f) + like % + cast(treeid as varchar) + %) from tree select iddboGetAncestors(id) (select count(*) from T where + dboGetAncestors(f) + like % + cast(treeid as varchar) + %) from tree /* 另外还要说一下封装的程度的问题具体情况具体分析 本题就不适合定义函数直接得到最终结果! 以上答案仅供参考!! 欢迎继续参与讨论! */ |