如何使用 SQL Server 2012 hierarchyid 获取递归级别?
How to get recursivelevel using SQL Server 2012 hierarchyid?
我知道这很有挑战性,有没有sql专家请帮助我解决这个问题。
我在 NameHID
列中有如下 hierarchyID
。分别代表/NameID/dadID/MomID/
。这意味着学生 fatherid 和 motherID。我的 Table 名字是学生。
这是我的示例NAMEHID
列
/2/8/5/
/5/11/12/
/8/7/9/
我需要像
这样的输出
NameID | RecursiveLevel
2 0
5 1
7 2
8 1
9 2
11 2
12 2
从这张图你可以看出什么是RecursiveLevel。这棵树代表某个特定节点的祖先。
我只需要在输出时显示 NameID 和递归级别。
如果有任何其他附加信息需要这样做吗?
您的数据不正确 hierachyid。
您可以使用拆分函数和 recursive cte
来完成您的工作
DECLARE @SampleData TABLE
(
NAMEHID varchar(30)
)
INSERT INTO @SampleData
(
NAMEHID
)
VALUES
('/2/8/5/'),('/5/11/12/'),('/8/7/9/')
;with temp AS
(
SELECT * FROM @SampleData sd
CROSS APPLY
(
SELECT * FROM [dbo].[SplitString](STUFF(LEFT(sd.NameHID,LEN(sd.NameHID) - 1),1,1,''),'/')
) cr
)
,cte AS
(
SELECT t.NameHID, t.[Value] , 0 AS Lvl FROM temp t
WHERE t.Pos = 1
AND NOT EXISTS (
SELECT * FROM temp t2
WHERE t2.[Value] = t.[Value] AND t2.Pos > 1
) -- root ID
UNION ALL
SELECT t2.NameHID, t2.[Value], cte.Lvl + 1
FROM cte
INNER JOIN temp t ON cte.[Value] = t.[Value] AND t.Pos = 1
INNER JOIN temp t2 ON t.NameHID = t2.NameHID AND t2.Pos > 1
)
SELECT cte.[Value] AS NameId, cte.Lvl
FROM cte
ORDER BY cte.Lvl, cte.[Value]
OPTION(MAXRECURSION 0)
拆分函数
CREATE FUNCTION [dbo].[SplitString] (@Text varchar(max),@Delimiter varchar(10))
Returns Table
As
Return (
Select Pos = Row_Number() over (Order By (Select null))
,Value = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)')))
From (Select x = Cast('<x>'+ Replace(@Text,@Delimiter,'</x><x>')+'</x>' as xml).query('.')) as A
Cross Apply x.nodes('x') AS B(i)
);
演示 link:http://rextester.com/KPX84657
我知道这很有挑战性,有没有sql专家请帮助我解决这个问题。
我在 NameHID
列中有如下 hierarchyID
。分别代表/NameID/dadID/MomID/
。这意味着学生 fatherid 和 motherID。我的 Table 名字是学生。
这是我的示例NAMEHID
列
/2/8/5/
/5/11/12/
/8/7/9/
我需要像
这样的输出NameID | RecursiveLevel
2 0
5 1
7 2
8 1
9 2
11 2
12 2
从这张图你可以看出什么是RecursiveLevel。这棵树代表某个特定节点的祖先。
我只需要在输出时显示 NameID 和递归级别。
如果有任何其他附加信息需要这样做吗?
您的数据不正确 hierachyid。
您可以使用拆分函数和 recursive cte
DECLARE @SampleData TABLE
(
NAMEHID varchar(30)
)
INSERT INTO @SampleData
(
NAMEHID
)
VALUES
('/2/8/5/'),('/5/11/12/'),('/8/7/9/')
;with temp AS
(
SELECT * FROM @SampleData sd
CROSS APPLY
(
SELECT * FROM [dbo].[SplitString](STUFF(LEFT(sd.NameHID,LEN(sd.NameHID) - 1),1,1,''),'/')
) cr
)
,cte AS
(
SELECT t.NameHID, t.[Value] , 0 AS Lvl FROM temp t
WHERE t.Pos = 1
AND NOT EXISTS (
SELECT * FROM temp t2
WHERE t2.[Value] = t.[Value] AND t2.Pos > 1
) -- root ID
UNION ALL
SELECT t2.NameHID, t2.[Value], cte.Lvl + 1
FROM cte
INNER JOIN temp t ON cte.[Value] = t.[Value] AND t.Pos = 1
INNER JOIN temp t2 ON t.NameHID = t2.NameHID AND t2.Pos > 1
)
SELECT cte.[Value] AS NameId, cte.Lvl
FROM cte
ORDER BY cte.Lvl, cte.[Value]
OPTION(MAXRECURSION 0)
拆分函数
CREATE FUNCTION [dbo].[SplitString] (@Text varchar(max),@Delimiter varchar(10))
Returns Table
As
Return (
Select Pos = Row_Number() over (Order By (Select null))
,Value = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)')))
From (Select x = Cast('<x>'+ Replace(@Text,@Delimiter,'</x><x>')+'</x>' as xml).query('.')) as A
Cross Apply x.nodes('x') AS B(i)
);
演示 link:http://rextester.com/KPX84657