1

我有一个 Group 表,在该表中,有一个 ParentId 列表示 Group 表中的组父级。目的是从这些组中构建一个动态菜单。我知道我可以循环并抓住最后一个孩子并构造一个结果集,但我很好奇是否有更多的 SQL-y 方式来实现这一点。

该表具有 int、int 和 varchar 的 Id、ParentId 和 Title 字段。

基本上,可以通过这种方式构建层次结构(人是基本组):

People -> Male   -> Boy
                 -> Man
       -> Female

我想抓住每个分支的最后一个孩子。所以,在这种情况下,{男孩,男人,女性}。

正如我所提到的,获取这些信息不是问题。我只是在寻找一种更好的方法来获得它,而不必编写一堆联合和循环,我基本上可以在其中更改基本组并动态地向外遍历整个层次结构。我不是真正的 Db 人,所以我不知道是否有一种巧妙的方法可以做到这一点。

4

2 回答 2

4

要获取多个层次结构之一的叶级别,您可以使用递归公用表表达式(CTE) 来枚举层次结构,然后检查哪些成员不是另一个组的父级以过滤到叶:

Declare @RootID int = 1

;with cte as (
  select 
    Id,
    ParentId,
    Title
  From
    Groups
  Where
    Id = @RootID
  Union All
  Select
    g.Id, 
    g.ParentId,
    g.Title
  From
    cte c
      Inner Join
    Groups g
      On c.Id = g.ParentID
)
Select
  *
From
  cte g
Where
  Not Exists (
    Select
      'x'
    From
      Groups g2
    Where
      g2.ParentID = g.Id
  );

您也可以使用左连接而不是不存在来执行此操作

http://sqlfiddle.com/#!6/8f1aa/9

于 2012-11-26T22:20:56.000 回答
1

由于您使用的是 SQL Server 2012,因此您可以利用hierarchyid; 下面是一个遵循 Laurence 模式的示例:

CREATE TABLE Groups
    (
      Id INT NOT NULL
             PRIMARY KEY
    , Title VARCHAR(20)
    , HID HIERARCHYID
    )

INSERT  INTO Groups
VALUES  ( 1, 'People', '/' ),
        ( 2, 'Male', '/1/' ),
        ( 3, 'Female', '/2/' ),
        ( 4, 'Boy', '/1/1/' ),
        ( 5, 'Man', '/1/2/' );

SELECT  Id
      , Title
FROM    Groups
WHERE   HID NOT IN ( SELECT HID.GetAncestor(1)
                     FROM   Groups
                     WHERE  HID.GetAncestor(1) IS NOT NULL )

http://sqlfiddle.com/#!6/00330/1/0

结果:

ID  TITLE
3   Female
4   Boy
5   Man
于 2012-11-26T22:41:20.033 回答