熱點推薦:
您现在的位置: 電腦知識網 >> 操作系統 >> Windows優化 >> 正文

樹型結構在關系表中的存儲及其應用處理

2013-11-12 16:44:21  來源: Windows優化 

  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 各個取值的記錄數?
  ID   Counts
     
     
     
     
     
     
     
  
  
  答案及簡單分析:
  
  /*
  看了前幾個人的答案似乎都把問題想復雜了游標臨時表遞歸
  游標臨時表 完全可以不用!
  遞歸 思想當然應是解決樹型結構的該想到的方法!
  但是 TSQL 的嵌套層次最多只能到 !
  icevi(按鈕工廠) 的建議是非常值得提倡的盡管 IDParentID 對於僅存儲是足夠經濟的
  但是若用其提供表現形式性能的確不會太好!
  許多高效的樹型結構論壇也確實是存儲並維護各個節點的層次信息的數據這樣
  顯示起來僅需一條 SQL 即可!
  下面是我的參考答案兩個自定義函數功能幾乎一樣都是運算出前面所提的
  應最好主動維護的層次信息:
  
  方法一: UDF 遞歸實現! 有 層嵌套限制
  */
  
  alter FUNCTION 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 @ReturnValue varchar()
  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
  
  /*
  另外還要說一下封裝的程度的問題具體情況具體分析
  本題就不適合定義函數直接得到最終結果!
  以上答案僅供參考!!
  歡迎繼續參與討論!
  */

From:http://tw.wingwit.com/Article/os/youhua/201311/10783.html
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.