【问题标题】:Find leaf nodes in hierarchical tree在层次树中查找叶节点
【发布时间】:2010-09-17 05:28:39
【问题描述】:

我的数据库中有一个存储树结构的表。以下是相关字段:

mytree (id, parentid, otherfields...)

我想找到所有的叶子节点(即id不是另一个记录的parentid的任何记录)

我试过了:

SELECT * FROM mytree WHERE `id` NOT IN (SELECT DISTINCT `parentid` FROM `mytree`)

但这返回了一个空集。奇怪的是,删除“NOT”会返回所有非叶节点的集合。

谁能看出我哪里出错了?

更新:感谢大家的回答,他们都是正确的并且为我工作。我接受了丹尼尔的,因为它也解释了为什么我的查询不起作用(NULL 的事情)。

【问题讨论】:

  • 使用建议的连接语法确实比使用子查询要好得多。
  • 其实,没有。任何中等体面的 RDBMS 都会根据需要将一个优化为另一个。最佳做法是使用最清楚地表达您的意图的任何形式。在这种情况下,该表单几乎毫无疑问是一个子查询。

标签: sql database tree


【解决方案1】:

您的查询无效,因为子查询包含NULL。以下轻微修改对我有用:

SELECT * FROM `mytree` WHERE `id` NOT IN (
    SELECT DISTINCT `parentid` FROM `mytree` WHERE `parentid` IS NOT NULL)

【讨论】:

  • 我们如何从特定的祖先获取叶节点?
【解决方案2】:

不知道为什么您的查询不起作用。这是左外连接语法中的相同内容 - 试试这种方式?

select a.*
from mytree a left outer join
     mytree b on a.id = b.parentid
where b.parentid is null

【讨论】:

    【解决方案3】:
    SELECT * FROM mytree AS t1
    LEFT JOIN mytree AS t2 ON t1.id=t2.parentid
    WHERE t2.parentid IS NULL
    

    【讨论】:

      【解决方案4】:
      Select * from mytree where id not in (Select distinct parentid from mytree where parentid is not null)
      

      http://archives.postgresql.org/pgsql-sql/2005-10/msg00228.php

      【讨论】:

        【解决方案5】:

        我的表结构是

        memberid    MemberID    joiningposition packagetype
        RPM00000    NULL          Root                free
        RPM71572    RPM00000       Left           Royal
        RPM323768   RPM00000       Right              Royal
        RPM715790   RPM71572       Left            free
        RPM323769   RPM71572      Right            free
        RPM715987   RPM323768      Left             free
        RPM323985   RPM323768      Right               free
        RPM733333   RPM323985     Right            free
        RPM324444   RPM715987     *emphasized text*Right               Royal
        

        --

        ALTER procedure [dbo].[sunnypro]
        as
        DECLARE @pId varchar(40) = 'RPM00000';
        Declare @Id int
        set @Id=(select id from registration where childid=@pId) 
        begin
        
        
        
        
        -- Recursive CTE
            WITH R AS
             (
        
        
        
        SELECT 
        
            BU.DateofJoing,
            BU.childid,
            BU.joiningposition,
            BU.packagetype
            FROM registration AS BU
            WHERE
            BU.MemberID = @pId and
           BU.joiningposition IN ('Left', 'Right')
            or BU.packagetype in('Royal','Platinum','Majestic')
             and BU.Id>@id
            UNION All
        
        -- Recursive part
        SELECT
        
             BU.DateofJoing,
             BU.childid,
             R.joiningposition,
            BU.packagetype
        
        
            FROM R
            JOIN registration AS BU
            ON BU.MemberID = R.childid
            WHERE
            BU.joiningposition IN ('Left', 'Right') and
          BU.packagetype in('Royal','Platinum','Majestic')
         and BU.Id>@id
        )
        
        INSERT INTO Wallatpayout
               (childid
               ,packagetype
        
               ,joiningposition
               ,DateofJoing
               ,Total)
        
        -- Final groups of nodes found
        SELECT top 3
        
        R.childid,
        R.packagetype,
        R.joiningposition,
        R.DateofJoing,
        Total = COUNT_BIG(*)
        FROM R where R.packagetype in('Royal','Platinum','Majestic')
        GROUP BY R.childid,
        R.joiningposition,
        R.DateofJoing,
        R.packagetype
        OPTION (MAXRECURSION 0);
        end
        

        【讨论】:

        • 嗯..问题或答案还是什么?老实说,不明白你想说什么:)
        猜你喜欢
        • 2015-09-15
        • 2019-04-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-11-21
        • 2020-05-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多