2012-07-05 59 views
1

設置:用於生成與SQL Server使用一個唯一的節點ID HIERARCHYID

MyTable (
    NodeId varchar(10), 
    ParentNodeId varchar(10), 
    NodeName varchar(50) 
) 

的NodeId不是數字,可以採取任何形式。多數的形式是Z123456,但有些是12345.

我想爲我的分層需求使用SqlServer HierarchyId數據類型。

問題:

我可以用一個CTE來生成我的節點和父層次,但我需要一個路徑傳遞到HIERARCHYID ::解析() - 遺憾的是,在形式Z123456一個NODEID不解析。如果NodeId和ParentNodeId是行ID整數,我會收拾起來,趕上我的火車回家看看我可愛的妻子,但相反,我在這裏盯着3360 x 1050分辨率。

我正在使用CTE來生成我的層次結構(並且我也可以在CTE中創建一個路徑),然後我附加行號給我獨特的整數ID,但是我將不得不重新運行使用生成的Ids生成我的路徑的分層CTE。

;with o as (
    select n.ParentNodeID, n.nodeid, n.NodeName, 1 as [level] 
    from Mytable n where n.ParentNodeID is null 
     union all 
    select n.ParentNodeID, n.nodeid, n.NodeName, o.[level] + 1 as [Level] 
    from MyTable n inner join o on n.ParentNodeID = o.NodeID 
) 
select NodeID, ParentNodeID, NodeDescription 
    , ROW_NUMBER() over (order by [level]) as hNodeId 
from o 

問:

反正我有可以實現的形式HIERARCHYID ::解析(路徑)將與一個CTE接受?例如/ 1/2/3/

TIA

回答

3
with C as 
(
    select T.NodeId, 
     T.ParentNodeId, 
     cast('/'+cast(row_number() over(order by T.NodeId) as varchar(10)) as varchar(max)) as HID 
    from MyTable as T 
    where T.ParentNodeId is null 
    union all 
    select T.NodeId, 
     T.ParentNodeId, 
     C.HID+'/'+cast(row_number() over(order by T.NodeId) as varchar(10)) 
    from MyTable as T 
    inner join C 
     on T.ParentNodeId = C.NodeId 
) 
select NodeId, 
     ParentNodeId, 
     HID, 
     hierarchyId::Parse(HID+'/') 
from C 
order by HID 

SQL-Fiddle

更新:
的研究的位表明,使用在遞歸CTE解析函數是不允許的。它在我的測試中有效,但如果我能想出替代解決方案,我會更新這個答案。

Omission about analytic and aggregate functions in CTEs

更新2:
顯然,這種解決方案是安全的使用,因爲它是在MSDN文檔。在CTE的遞歸部分
WITH common_table_expression (Transact-SQL)

解析與聚集函數也 施加到該組當前遞歸層次,而不是該組 爲CTE。像ROW_NUMBER功能只對當前遞歸級別傳遞給他們 數據,而不是整個 集pased的CTE

+0

感謝的Mikael的遞歸部分數據的子集進行操作。我正在做一些測試,因爲我的層次非常深,產生了一個像/ 1/1/1/1/1/1/1/1/12這樣的路徑 - 確保我可以得到祖先和後代。我想到的一個解決方案是從MyTable到一個CTE做一個Select *,row_number()..作爲行,然後在該行上使用'row'列做遞歸CTE,但是我的遞歸CTE非常慢(結果集是〜25000行)。當我將這個邏輯應用於我的代碼時,我會進行更新。 – 2012-07-05 15:43:02

+0

不要做一個使用CTE作爲數據源的遞歸CTE。它非常慢,因爲每次迭代都會重新生成第一個CTE(帶有row_number)。如果你真的需要這樣做,最好使用臨時表。 – 2012-07-05 15:48:58

+0

ParentNodeId上的索引可能會加速一點。 – 2012-07-05 15:51:08