8

使用t-sql 层次结构ID 如何获取所有没有子代的行(即最后一个后代)?

假设我的表结构如下:

 Id, 
 Name,
 HierarchyId

并有这些行:

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

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

什么问题会给我约翰和克里斯?

4

3 回答 3

14

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

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)
于 2011-12-19T14:21:57.883 回答
1

由于您只需要叶子并且不需要从特定的祖先获取它们,因此像这样的简单非递归查询应该可以完成工作:

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
    )

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

于 2011-12-19T13:57:42.473 回答
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
于 2015-03-02T13:56:25.263 回答