HierarchyID如何从子级获取所有父级

时间:2011-03-18 06:26:51

标签: hierarchyid

我对菜单的hierarchyID和UserRights有问题。我只想给用户4级权限,我的QUery应该自动从4级孩子中选择所有父级。 怎么做?

你了解我的问题吗?我只想要一个孩子的所有父母(祖先)。

Greets Manuel

4 个答案:

答案 0 :(得分:3)

这样的东西避免了CTE

SELECT t1.NodeId.ToString(), t1.Name
    FROM (SELECT * FROM test_table2
        WHERE Name = 'Node 1.1.1') t2
    , test_table2 t1
    WHERE
        t1.NodeId = t2.NodeId OR
        t2.NodeId.IsDescendantOf(t1.NodeId) = 1

答案 1 :(得分:3)

我最近一直在使用HierarchyId工作,我遇到了这个问题,寻找不同问题的答案。我以为我会把这个例子放在混合中,因为它占了一些东西。首先,您可以在没有递归CTE的情况下获取条件表达式。其次,GetDescendantOf是包容性的,因此您不需要检查t1.NodeId = t2.NodeId(我通常更喜欢加入子查询)。这是一个你可以玩的完整演示:

BEGIN TRANSACTION

CREATE TABLE #HierarchyDemo
(
    NodeId HIERARCHYID PRIMARY KEY NOT NULL,
    Description AS NodeId.ToString(),
    Depth AS NodeId.GetLevel()
)

INSERT INTO #HierarchyDemo VALUES ( HierarchyId::GetRoot() );
INSERT INTO #HierarchyDemo VALUES ( CAST ('/1979/' AS HIERARCHYID) );
INSERT INTO #HierarchyDemo VALUES ( CAST ('/2012/' AS HIERARCHYID) );
INSERT INTO #HierarchyDemo VALUES ( CAST ('/2012/2/' AS HIERARCHYID) );
INSERT INTO #HierarchyDemo VALUES ( CAST ('/1979/4/' AS HIERARCHYID) );
INSERT INTO #HierarchyDemo VALUES ( CAST ('/2012/2/17/' AS HIERARCHYID) );
INSERT INTO #HierarchyDemo VALUES ( CAST ('/1979/4/6/' AS HIERARCHYID) );

SELECT *
FROM #HierarchyDemo;

SELECT *
FROM #HierarchyDemo startingPoint
INNER JOIN #HierarchyDemo parent
    ON startingPoint.NodeId.IsDescendantOf(parent.NodeId) = 1
WHERE startingPoint.Description = '/2012/2/17/'

ROLLBACK TRANSACTION

答案 2 :(得分:1)

假设你有这张表:

CREATE TABLE Hierarchy
(
    CompanyNode hierarchyid NOT NULL,
    CompanyId int NOT NULL,
    NodeLevel AS CompanyNode.GetLevel()
    CONSTRAINT PK_Hierarchy PRIMARY KEY NONCLUSTERED (CompanyNode)
)

并填充它以保存此数据:

CompanyNode CompanyId NodeLevel
0x  1   0
0x58    2   1
0x5AC0  3   2
0x68    100 1
0x6AC0  101 2
0x6AD6  1000    3
0x6AD6B0    10000   4
0x78    20  1
0x7AC0  200 2
0x7AD6  2000    3
0x7AD6B0    20000   4
0x7AD6B580  200000  5
0x7AD6D0    20001   4
0x7ADA  2001    3
0x7ADE  2002    3
0x7B40  201 2
0x7BC0  202 2

现在你想得到CompanyId 20001的所有父母,我就这样做了:

DECLARE @currentLevel smallint

SELECT  @currentLevel = NodeLevel
FROM    Hierarchy
WHERE   CompanyId = 20001;

with tree([Path], [PathName], CompanyId, [Level])
AS
(
SELECT  h.CompanyNode AS [Path],
        h.CompanyNode.ToString() AS [PathName],
        h.CompanyId,
        @currentLevel AS [Level]
FROM    Hierarchy h
WHERE   h.CompanyId = 20001

UNION ALL

SELECT  h.CompanyNode AS [Path],
        h.CompanyNode.ToString() AS [PathName],
        h.CompanyId,
        CAST((t.[Level] - 1) AS smallint) AS [Level]
FROM    Hierarchy h
        INNER JOIN tree t ON
            t.[Path].GetAncestor(1) = h.CompanyNode
    WHERE   h.[NodeLevel] > 0
)   
SELECT * FROM TREE
order by [Path]

您可以更改CTE的递归部分,而不是过滤树的最顶层节点。

希望这有帮助,

乌迪德

答案 3 :(得分:0)

Declare @hid hierarchyid=0x5D10 -- Child hierarchy id

SELECT
*
FROM 
  dbo.TableName
WHERE 
  @hid.IsDescendantOf(ParentHierarchyId) = 1