【问题标题】:Is there a better way to get the last level of groups from a table?有没有更好的方法从表中获取最后一级的组?
【发布时间】:2012-11-26 22:14:25
【问题描述】:

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

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

基本上,可以这样构建层次结构(人是基组):

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

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

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

【问题讨论】:

    标签: sql sql-server-2012


    【解决方案1】:

    要获取多个层次结构之一的叶级别,您可以使用 Recursive Common Table Expressions (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

    【讨论】:

    • 感谢您的回答。一个问题:但是,我如何才能只为 Person 获得这些结果?这将为我提供所有层次结构的最后一层。
    • @Yatrix 已更新为执行此操作。
    【解决方案2】:

    由于您使用的是 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
    

    【讨论】:

    • 我不想换桌子。还是)感谢你的建议。必须牢记这一点。
    猜你喜欢
    • 1970-01-01
    • 2019-03-28
    • 2014-05-14
    • 2021-07-05
    • 1970-01-01
    • 2020-06-21
    • 1970-01-01
    • 2017-09-03
    • 1970-01-01
    相关资源
    最近更新 更多