2011-12-19 42 views
7

使用t-sqlhierarchy我如何獲得所有沒有孩子(這是最後的死者)的行?Sql HierarchyId我如何得到最後的後代?

說我的表的結構是這樣的:

Id, 
Name, 
HierarchyId 

而且具有這些行:

1, Craig,/
2, Steve, /1/ 
3, John, /1/1/ 

4, Sam, /2/ 
5, Matt, /2/1/ 
6, Chris, /2/1/1/ 

什麼查詢會給我約翰和克里斯?

回答

9

也許有更好的方法,但這接合來完成這項工作。

declare @T table 
(
    ID int, 
    Name varchar(10), 
    HID HierarchyID 
) 

insert into @T values 
(1, 'Craig', '/'), 
(2, 'Steve', '/1/'), 
(3, 'John', '/1/1/'), 
(4, 'Sam', '/2/'), 
(5, 'Matt', '/2/1/'), 
(6, 'Chris', '/2/1/1/') 

select * 
from @T 
where HID.GetDescendant(null, null) not in (select HID 
              from @T) 

結果:

ID   Name  HID 
----------- ---------- --------------------- 
3   John  0x5AC0 
6   Chris  0x6AD6 

更新如果節點號未處於不間斷的序列上方2012-05-22

查詢將失敗。這是另一個應該注意的版本。

declare @T table 
(
    ID int, 
    Name varchar(10), 
    HID HierarchyID 
) 

insert into @T values 
(1, 'Craig', '/'), 
(2, 'Steve', '/1/'), 
(3, 'John', '/1/1/'), 
(4, 'Sam', '/2/'), 
(5, 'Matt', '/2/1/'), 
(6, 'Chris', '/2/1/2/') -- HID for this row is changed compared to above query 

select * 
from @T 
where HID not in (select HID.GetAncestor(1) 
        from @T 
        where HID.GetAncestor(1) is not null) 
1

既然你只需要葉子,你不需要從一個特定的祖先讓他們,這樣一個簡單的非遞歸查詢應該做的工作:

SELECT * FROM YOUR_TABLE PARENT 
WHERE 
    NOT EXISTS (
     SELECT * FROM YOUR_TABLE CHILD 
     WHERE CHILD.HierarchyId = PARENT.Id 
    ) 

用簡單的英語:選擇的每一行沒有孩子排。

這裏假設您的HierarchyId是一個對於Id的FOREIGN KEY,而不是整個「路徑」,如您的示例所示。如果不是,這可能是您應該在數據庫模型中修復的第一件事。

---編輯---

OK,下面是實際工作的MS SQL Server特定的查詢:

SELECT * FROM YOUR_TABLE PARENT 
WHERE 
    NOT EXISTS (
     SELECT * FROM YOUR_TABLE CHILD 
     WHERE 
      CHILD.Id <> PARENT.Id 
      AND CHILD.HierarchyId.IsDescendantOf(PARENT.HierarchyId) = 1 
    ) 

注意,IsDescendantOf認爲任何行自身的後代,所以我們還需要CHILD.Id <> PARENT.Id這個條件。

+0

我相當肯定的是OP使用SQL Server 2008,這也解釋了不尋常的表現的'HierarchyID'數據類型(見http://msdn.microsoft.com/en-us/magazine/cc794278的.aspx)。 – 2011-12-19 14:01:28

+0

@DanielPratt啊......我現在看到這個問題被重新標記爲[sql-server]。 – 2011-12-19 14:04:15

+0

感謝您的Branko,但在我的示例中,Id字段是整數,HierarchyId是sql HierarchyId,因此無法進行比較。你是否說我需要將表格的關鍵字改爲hierarchyId? – Eric 2011-12-19 14:13:07

1

嗨我使用這一個,併爲我完美的作品。

CREATE TABLE [dbo].[Test]([Id] [hierarchyid] NOT NULL, [Name] [nvarchar](50) NULL) 
DECLARE @Parent AS HierarchyID = CAST('/2/1/' AS HierarchyID) -- Get Current Parent 
DECLARE @Last AS HierarchyID 
SELECT @Last = MAX(Id) FROM Test WHERE Id.GetAncestor(1) = @Parent -- Find Last Id for this Parent 

INSERT INTO Test(Id,Name) VALUES(@Parent.GetDescendant(@Last, NULL),'Sydney') -- Insert after Last Id