在一個表中,有這樣的一個層級關系,ID為主鍵,PId為父級ID
關系如下圖:
然后呢,現在的需求是,已知某一條記錄的ID,求出它頂層父級的ID,也就是我們所謂的“尋根”計划。
這類問題解決方法很多,首先我用SQL中的函數來解決,許久不寫,正好練習一下:
1 --創建函數 2 CREATE function F_FindPIdByID 3 ( 4 @ID varchar(15) --參數 5 ) 6 returns varchar(500) 7 as 8 begin 9 10 declare @PId varchar(15) --變量父級ID,當前ID的PID 11 declare @Place varchar(500) --變量Place,最終返回結果 12 set @Place = '0' 13 begin 14 --首先根據傳入的ID獲取其父ID,PID 15 SELECT @PId = PId FROM T_Recursion 16 where ID = @ID 17 end 18 19 if (@PId<> '0')--如果不是根節點 20 begin 21 -- 再將@PID 作為參數@ID傳入函數進行自調用 22 set @Place =dbo.F_FindPIdByID(@PId); 23 end 24 else 25 begin 26 --滿足PId=0這個條件,則把當前傳入函數中的ID賦值並返回,即當前的PId就是最終要獲取到的ID 27 set @Place =@ID 28 end 29 return @Place 30 end 31 go
函數創建好了(有點遞歸的味道)
下面給定參數,然后執行函數,看看結果
1 --測試A 2 select dbo.F_FindPIdByID(1111) as 'ID' 3 4 --測試B 5 select dbo.F_FindPIdByID(21) as 'ID' 6 7 --測試C 8 select dbo.F_FindPIdByID(31) as 'ID'
測試的結果



大功告成。
接下來,我們試試另一個方法。直接寫查詢語句來實現,這里要用到[ WITH AS ]。
什么是WITH AS?
1、WITH AS短語,也叫做子查詢部分(subquery factoring),可以定義一個SQL片斷,該SQL片斷會被整個SQL語句用到。可以使SQL語句的可讀性更高,也可以在UNION ALL的不同部分,作為提供數據的部分。
2、對於UNION ALL,使用WITH AS定義了一個UNION ALL語句,當該片斷被調用2次以上,優化器會自動將該WITH AS短語所獲取的數據放入一個Temp表中。而提示meterialize則是強制將WITH AS短語的數據放入一個全局臨時表中。很多查詢通過該方式都可以提高速度。
搞清楚什么是 with as,我們就來用一下,核心思想是ID作為PId條件找到上級ID
1 with Tree AS 2 ( 3 SELECT * FROM T_Recursion WHERE ID = 1111 4 UNION ALL 5 SELECT a.* FROM Tree , T_Recursion as a WHERE Tree.PId = a.ID 6 ) 7 SELECT * FROM Tree order by ID ASC;
執行一下,我們發現結果是所有與之相關的記錄:
,目的達到,完結撒花...