有没有更好的方法从表中获取最后一组的组?

时间:2012-11-26 22:14:25

标签: sql sql-server-2012

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

该表包含int,int和varchar的Id,ParentId和Title字段。

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

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

我想抓住每个分支的最后一个孩子。所以,{Boy,Man,Female}在这种情况下。

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

2 个答案:

答案 0 :(得分:4)

要获取多个层次结构之一的叶级别,可以使用Recursive Common Table Expressions(CTE)枚举层次结构,然后检查哪些成员不是另一个组的父级,以过滤到叶子:< / p>

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

答案 1 :(得分:1)

由于您使用的是SQL Server 2012,因此您可以利用hierarchyid;这是劳伦斯的架构之后的一个例子:

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