HierarchyID Как получить всех родителей от ребенка - PullRequest
6 голосов
/ 18 марта 2011

У меня проблема с иерархией ID и правами пользователя для меню. Я только хочу дать пользователю право на уровень 4, например, и мой запрос должен автоматически выбрать всех родителей из уровня 4 ребенка. Как это сделать?

Ты понимаешь мою проблему? Я просто хочу, чтобы все родители (предки) были от ребенка.

Приветствует Мануэля

Ответы [ 4 ]

3 голосов
/ 03 августа 2011

Нечто подобное избегает 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
3 голосов
/ 20 марта 2013

В последнее время я много работал с 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
1 голос
/ 27 апреля 2011

давайте предположим, что у вас есть эта таблица:

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 и не фильтровать самый верхний узел дерева.

надеюсь, это поможет,

Одед

0 голосов
/ 22 января 2014
Declare @hid hierarchyid=0x5D10 -- Child hierarchy id

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