Sql-Server

HierarchyID:獲取父母列表的所有後代

  • August 1, 2014

我有一個這樣的父 ID 列表,100, 110, 120, 130它是動態的並且可以更改。我想在一組中獲取指定父母的所有後代。為了獲得一個單親的孩子,我使用了這樣的查詢:

WITH parent AS (
   SELECT PersonHierarchyID FROM PersonHierarchy
   WHERE PersonID = 100    
)
SELECT * FROM PersonHierarchy
WHERE PersonHierarchyID.IsDescendantOf((SELECT * FROM parent)) = 1

不知道如何為多個父母做到這一點。我的第一次嘗試是寫幾個聯合之類的東西,但是我確信應該有更聰明的方法來做這件事。

SELECT * FROM PersonHierarchy 
WHERE PersonHierarchyID.IsDescendantOf(
   (SELECT PersonHierarchyID FROM PersonHierarchy WHERE PersonID = 100)
) = 1
UNION ALL
SELECT * FROM PersonHierarchy 
WHERE PersonHierarchyID.IsDescendantOf(
   (SELECT PersonHierarchyID FROM PersonHierarchy WHERE PersonID = 110)
) = 1
UNION ALL ...

PS我還發現這樣的查詢來選擇可能有幫助的ID列表:

SELECT * FROM (VALUES (100), (110), (120), (130)) AS Parent(ParentID)

總而言之,我的目標是編寫接受父 ID 數組作為參數的查詢,並在一個集合中返回它們的所有後代。

實現此目的的一種方法是:

USE tempdb;
CREATE TABLE dbo.PersonHierarchy
(
   PersonHierarchyID HierarchyID
);

INSERT INTO dbo.PersonHierarchy VALUES ('/1/');
INSERT INTO dbo.PersonHierarchy VALUES ('/1/1/');
INSERT INTO dbo.PersonHierarchy VALUES ('/1/2/');
INSERT INTO dbo.PersonHierarchy VALUES ('/2/');
INSERT INTO dbo.PersonHierarchy VALUES ('/2/1/');

SELECT *
FROM dbo.PersonHierarchy;

DECLARE @T TABLE 
(
   PersonHierarchyID HierarchyID
);

INSERT INTO @T
VALUES ('/1/'), ('/2/');

WITH parent AS (
   SELECT p.PersonHierarchyID 
   FROM dbo.PersonHierarchy p
       INNER JOIN @T t ON p.PersonHierarchyID = t.PersonHierarchyID
)
SELECT ph.PersonHierarchyID.ToString(), parent.PersonHierarchyID.ToString() /* select only the necessary columns, do NOT use SELECT *  */
FROM dbo.PersonHierarchy ph
   INNER JOIN parent ON ph.PersonHierarchyID.IsDescendantOf(parent.PersonHierarchyID) = 1
ORDER BY ph.PersonHierarchyID; /* always include an ORDER BY */

引用自:https://dba.stackexchange.com/questions/72936