Sql HierarchyId如何获取最后的后代?

Sql HierarchyId如何获取最后的后代?,sql,sql-server,hierarchyid,Sql,Sql Server,Hierarchyid,使用t-sql Id如何获取没有子级的所有行(即最后一个decentant) 假设我的表的结构如下: Id, Name, HierarchyId 有以下几行: 1, Craig, / 2, Steve, /1/ 3, John, /1/1/ 4, Sam, /2/ 5, Matt, /2/1/ 6, Chris, /2/1/1/ 什么查询会给我John和Chris?因为您只需要leaf,而不需要从特定的祖先那里获取它们,像这样一个简单的非递归查询应该可以完成这项工作: SELECT

使用t-sql Id如何获取没有子级的所有行(即最后一个decentant)

假设我的表的结构如下:

 Id, 
 Name,
 HierarchyId
有以下几行:

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

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

什么查询会给我John和Chris?

因为您只需要leaf,而不需要从特定的祖先那里获取它们,像这样一个简单的非递归查询应该可以完成这项工作:

SELECT * FROM YOUR_TABLE PARENT
WHERE
    NOT EXISTS (
        SELECT * FROM YOUR_TABLE CHILD
        WHERE CHILD.HierarchyId = PARENT.Id
    )
简体中文:选择没有子行的每一行

这假设您的HierarchyId是指向该Id的外键,而不是示例中所示的整个路径。如果不是,这可能是您应该在数据库模型中修复的第一件事

--编辑--

好的,下面是实际工作的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
    )

请注意,isDescendatof将任何一行视为其自身的后代,因此我们还需要条件中的CHILD.Id PARENT.Id。

也许有更好的方法,但这可以完成这项工作

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)

嗨,我用这个,非常适合我

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

我相当肯定OP使用的是SQL Server 2008的HierarchyID数据类型,这就解释了这种不寻常的表示形式。请参见。@DanielPratt Ahh。。。现在我看到问题被重新标记为[sql server]。感谢您的回复,但在我的示例中,Id字段是一个整数,而HierarchyId是一个sql HierarchyId,因此无法对它们进行比较。您是说我需要将表的键更改为hierarchyId吗?@EricNeifert我假设您使用的是经典设计来表示关系数据库中的分层数据,而不是MS SQL Server特定的机制。不幸的是,我对特定于MS SQL Server的机制还不太熟悉,因此无法建议您是否实际进行切换,但似乎同样的基本思想也可以应用于MS SQL Server—请参阅。